Copy-paste patterns
Code examples
Worked samples in JavaScript, Python, and PHP for the three integrations most teams build first: fetch a term, render JSON-LD, build a CRediT statement.
Pattern 1 — Fetch a dictionary term
Read a single term by slug from the GraphQL endpoint. The same call works against the production endpoint and the local development endpoint; only the URL changes.
const ENDPOINT = "https://casrai.org/graphql";
async function fetchTerm(slug) {
const res = await fetch(ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
query: `
query GetTerm($slug: ID!) {
dictionaryTerm(id: $slug, idType: SLUG) {
slug title status version canonicalUri
definitionOperational
examples counterExamples aliases
dictionaryDomains { nodes { slug name } }
}
}
`,
variables: { slug },
}),
});
const { data, errors } = await res.json();
if (errors) throw new Error(errors[0].message);
return data.dictionaryTerm;
}
const term = await fetchTerm("research-integrity");
console.log(`${term.title} (${term.status}, ${term.version})`);
console.log(term.definitionOperational);import requests
ENDPOINT = "https://casrai.org/graphql"
QUERY = """
query GetTerm($slug: ID!) {
dictionaryTerm(id: $slug, idType: SLUG) {
slug title status version canonicalUri
definitionOperational
examples counterExamples aliases
dictionaryDomains { nodes { slug name } }
}
}
"""
def fetch_term(slug: str) -> dict:
r = requests.post(
ENDPOINT,
json={"query": QUERY, "variables": {"slug": slug}},
timeout=10,
)
r.raise_for_status()
payload = r.json()
if payload.get("errors"):
raise RuntimeError(payload["errors"][0]["message"])
return payload["data"]["dictionaryTerm"]
term = fetch_term("research-integrity")
print(f"{term['title']} ({term['status']}, {term['version']})")
print(term["definitionOperational"])<?php
declare(strict_types=1);
const CASRAI_ENDPOINT = "https://casrai.org/graphql";
function casrai_fetch_term(string $slug): array {
$query = <<<'GQL'
query GetTerm($slug: ID!) {
dictionaryTerm(id: $slug, idType: SLUG) {
slug title status version canonicalUri
definitionOperational
examples counterExamples aliases
dictionaryDomains { nodes { slug name } }
}
}
GQL;
$body = json_encode(["query" => $query, "variables" => ["slug" => $slug]]);
$ch = curl_init(CASRAI_ENDPOINT);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_POSTFIELDS => $body,
CURLOPT_TIMEOUT => 10,
]);
$raw = curl_exec($ch);
curl_close($ch);
$payload = json_decode($raw, true);
if (!empty($payload["errors"])) {
throw new RuntimeException($payload["errors"][0]["message"]);
}
return $payload["data"]["dictionaryTerm"];
}
$term = casrai_fetch_term("research-integrity");
echo "{$term['title']} ({$term['status']}, {$term['version']})\n";
echo $term["definitionOperational"], "\n";Pattern 2 — Render JSON-LD for a term
Emit a Schema.org-aligned DefinedTerm payload for a dictionary record, suitable for embedding in a page‘s <script type="application/ld+json"> block. See CRediT in JSON-LD for the schema rationale.
function termToJsonLd(term) {
return {
"@context": "https://schema.org",
"@type": "DefinedTerm",
"@id": term.canonicalUri,
name: term.title,
identifier: term.canonicalUri,
description: term.definitionOperational,
inDefinedTermSet: "https://casrai.org/dictionary",
url: term.canonicalUri,
sameAs: term.aliases ?? [],
license: "https://creativecommons.org/licenses/by/4.0/",
};
}
const jsonLd = termToJsonLd(await fetchTerm("research-integrity"));
process.stdout.write(JSON.stringify(jsonLd, null, 2));import json
def term_to_jsonld(term: dict) -> dict:
return {
"@context": "https://schema.org",
"@type": "DefinedTerm",
"@id": term["canonicalUri"],
"name": term["title"],
"identifier": term["canonicalUri"],
"description": term["definitionOperational"],
"inDefinedTermSet": "https://casrai.org/dictionary",
"url": term["canonicalUri"],
"sameAs": term.get("aliases") or [],
"license": "https://creativecommons.org/licenses/by/4.0/",
}
print(json.dumps(term_to_jsonld(fetch_term("research-integrity")), indent=2))<?php
function term_to_jsonld(array $term): array {
return [
"@context" => "https://schema.org",
"@type" => "DefinedTerm",
"@id" => $term["canonicalUri"],
"name" => $term["title"],
"identifier" => $term["canonicalUri"],
"description" => $term["definitionOperational"],
"inDefinedTermSet" => "https://casrai.org/dictionary",
"url" => $term["canonicalUri"],
"sameAs" => $term["aliases"] ?? [],
"license" => "https://creativecommons.org/licenses/by/4.0/",
];
}
echo json_encode(
term_to_jsonld(casrai_fetch_term("research-integrity")),
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES
);Pattern 3 — Build a CRediT contributor statement
Given a list of contributors with their CRediT roles, produce the human-readable "Author contributions" paragraph that most journals expect alongside the structured JATS markup. Each role is rendered with the canonical wording and the optional degree.
/**
* contributors: [
* { name: "San Zhang", roles: [
* { slug: "conceptualization" },
* { slug: "software", degree: "lead" }
* ]}
* ]
*/
const ROLE_LABELS = {
"conceptualization": "Conceptualization",
"data-curation": "Data curation",
"formal-analysis": "Formal analysis",
"funding-acquisition": "Funding acquisition",
"investigation": "Investigation",
"methodology": "Methodology",
"project-administration": "Project administration",
"resources": "Resources",
"software": "Software",
"supervision": "Supervision",
"validation": "Validation",
"visualization": "Visualization",
"writing-original-draft": "Writing - original draft",
"writing-review-editing": "Writing - review & editing",
};
function buildCreditStatement(contributors) {
return contributors.map(({ name, roles }) => {
const parts = roles.map(r => {
const label = ROLE_LABELS[r.slug] ?? r.slug;
return r.degree ? `${label} (${r.degree})` : label;
});
return `${name}: ${parts.join("; ")}.`;
}).join(" ");
}
console.log(buildCreditStatement([
{ name: "San Zhang", roles: [
{ slug: "conceptualization" },
{ slug: "software", degree: "lead" },
{ slug: "writing-original-draft", degree: "supporting" },
]},
{ name: "Mei Liu", roles: [
{ slug: "investigation", degree: "lead" },
{ slug: "formal-analysis" },
]},
]));ROLE_LABELS = {
"conceptualization": "Conceptualization",
"data-curation": "Data curation",
"formal-analysis": "Formal analysis",
"funding-acquisition": "Funding acquisition",
"investigation": "Investigation",
"methodology": "Methodology",
"project-administration": "Project administration",
"resources": "Resources",
"software": "Software",
"supervision": "Supervision",
"validation": "Validation",
"visualization": "Visualization",
"writing-original-draft": "Writing - original draft",
"writing-review-editing": "Writing - review & editing",
}
def build_credit_statement(contributors: list[dict]) -> str:
sentences = []
for c in contributors:
parts = []
for r in c["roles"]:
label = ROLE_LABELS.get(r["slug"], r["slug"])
parts.append(f"{label} ({r['degree']})" if r.get("degree") else label)
sentences.append(f"{c['name']}: {'; '.join(parts)}.")
return " ".join(sentences)
print(build_credit_statement([
{"name": "San Zhang", "roles": [
{"slug": "conceptualization"},
{"slug": "software", "degree": "lead"},
{"slug": "writing-original-draft", "degree": "supporting"},
]},
{"name": "Mei Liu", "roles": [
{"slug": "investigation", "degree": "lead"},
{"slug": "formal-analysis"},
]},
]))<?php
const ROLE_LABELS = [
"conceptualization" => "Conceptualization",
"data-curation" => "Data curation",
"formal-analysis" => "Formal analysis",
"funding-acquisition" => "Funding acquisition",
"investigation" => "Investigation",
"methodology" => "Methodology",
"project-administration" => "Project administration",
"resources" => "Resources",
"software" => "Software",
"supervision" => "Supervision",
"validation" => "Validation",
"visualization" => "Visualization",
"writing-original-draft" => "Writing - original draft",
"writing-review-editing" => "Writing - review & editing",
];
function build_credit_statement(array $contributors): string {
$sentences = [];
foreach ($contributors as $c) {
$parts = [];
foreach ($c["roles"] as $r) {
$label = ROLE_LABELS[$r["slug"]] ?? $r["slug"];
$parts[] = isset($r["degree"]) ? "{$label} ({$r['degree']})" : $label;
}
$sentences[] = "{$c['name']}: " . implode("; ", $parts) . ".";
}
return implode(" ", $sentences);
}
echo build_credit_statement([
["name" => "San Zhang", "roles" => [
["slug" => "conceptualization"],
["slug" => "software", "degree" => "lead"],
["slug" => "writing-original-draft", "degree" => "supporting"],
]],
["name" => "Mei Liu", "roles" => [
["slug" => "investigation", "degree" => "lead"],
["slug" => "formal-analysis"],
]],
]);Where to go next
- GraphQL endpoint — the full schema and authentication notes.
- REST endpoints — for HTTP pipelines that do not speak GraphQL.
- CRediT in JATS XML — for production systems emitting JATS.
- CRediT in JSON-LD — for headless publishing.
- External: JATS4R CRediT recommendation — the authoritative XML encoding.








