Skip to content

Quickstart

This walkthrough goes from nothing to queryable impact data. All you need is curl.

Sign in at app.cast.commonapproach.org, open API in the sidebar, and create a key under the Settings tab.

Set up your shell for the rest of the walkthrough:

Terminal window
BASE=https://api.cast.commonapproach.org
KEY=your-api-key-here

A namespace is an isolated dataset within your tenant. Every data request names one explicitly — nothing is shared between namespaces.

Terminal window
curl -s -X POST $BASE/namespaces \
-H "X-API-Key: $KEY" -H "Content-Type: application/json" \
-d '{"namespace": "quickstart", "label": "Quickstart walkthrough"}'

Namespace slugs are lowercase letters, digits, and hyphens (^[a-z0-9][a-z0-9-]{0,62}$). Creation is idempotent. From here on, every request carries both the X-API-Key and X-Namespace headers. Namespaces can also be created in the console under API → Settings.

Option A — upload a capsule (if you already have CIDS JSON-LD, e.g. an export from an aligned platform):

Terminal window
curl -X POST $BASE/capsules \
-H "X-API-Key: $KEY" -H "X-Namespace: quickstart" \
-H "Content-Type: application/json" \
--data-binary @my-capsule.jsonld
{"capsule_id": "9f3c1a7e5b2d4c88a1e6f04d7b92c3aa", "status": "pending"}

Processing is asynchronous — poll with the capsule_id from the response until the status is accepted or rejected:

Terminal window
curl -H "X-API-Key: $KEY" -H "X-Namespace: quickstart" \
$BASE/capsules/9f3c1a7e5b2d4c88a1e6f04d7b92c3aa

A rejected capsule stores nothing and returns a plain-language validation report you can forward to whoever produced the file. See Capsules.

Option B — build it with CRUD calls. Every create supplies the entity’s own URI — Graph Cast never invents identifiers (see Identifiers) — and returns an id you use in the next call’s URL.

Create an organization:

Terminal window
curl -X POST $BASE/orgs \
-H "X-API-Key: $KEY" -H "X-Namespace: quickstart" \
-H "Content-Type: application/json" \
-d '{"uri": "https://greenfield.example/org/ghc",
"name": "Greenfield Housing Co-op"}'
{"id": "ag7kailrb32j2djhdxlxv42vs4", "uri": "https://greenfield.example/org/ghc", }

Give it an outcome:

Terminal window
curl -X POST $BASE/orgs/ag7kailrb32j2djhdxlxv42vs4/outcomes \
-H "X-API-Key: $KEY" -H "X-Namespace: quickstart" \
-H "Content-Type: application/json" \
-d '{"uri": "https://greenfield.example/outcome/housing-stability",
"name": "Housing stability",
"themes": ["https://metadata.un.org/sdg/1"]}'
{"id": "qmcsw2qasowhmd6cs4nozkylsa", }

An indicator that measures the outcome:

Terminal window
curl -X POST $BASE/orgs/ag7kailrb32j2djhdxlxv42vs4/indicators \
-H "X-API-Key: $KEY" -H "X-Namespace: quickstart" \
-H "Content-Type: application/json" \
-d '{"uri": "https://greenfield.example/indicator/tenant-retention",
"name": "Tenant retention rate (%)",
"unit": "%",
"outcome_id": "qmcsw2qasowhmd6cs4nozkylsa"}'
{"id": "mwv3xpkiyefhv26l3kdwolrzaa", }

And a report with a value:

Terminal window
curl -X POST $BASE/indicators/mwv3xpkiyefhv26l3kdwolrzaa/reports \
-H "X-API-Key: $KEY" -H "X-Namespace: quickstart" \
-H "Content-Type: application/json" \
-d '{"uri": "https://greenfield.example/report/tenant-retention-2025",
"value": 94, "unit": "%",
"period_start": "2025-01-01", "period_end": "2025-12-31"}'

Re-running any of these with the same URIs is a safe upsert — re-POSTing a report URI with a corrected value replaces it.

Terminal window
# every indicator report, denormalized (indicator, outcome, themes, org on each row)
curl -H "X-API-Key: $KEY" -H "X-Namespace: quickstart" \
"$BASE/rows/indicator-reports?limit=50"
# what themes exist, with report counts — feed for a filter picker
curl -H "X-API-Key: $KEY" -H "X-Namespace: quickstart" \
$BASE/rows/themes
# filter: one theme, one year (period is an overlap filter)
curl -H "X-API-Key: $KEY" -H "X-Namespace: quickstart" \
"$BASE/rows/indicator-reports?theme=https%3A%2F%2Fmetadata.un.org%2Fsdg%2F1&period[from]=2025-01-01&period[to]=2025-12-31"
# one organization's full theory of change as a tree
curl -H "X-API-Key: $KEY" -H "X-Namespace: quickstart" \
$BASE/orgs/ag7kailrb32j2djhdxlxv42vs4/everything
# everything in the namespace as CIDS JSON-LD
curl -H "X-API-Key: $KEY" -H "X-Namespace: quickstart" \
$BASE/export

See Querying for the full filter reference.

  • Identifiers — how entity identity works (required reading before a real integration).
  • Capsules — validation rules, rollback, and modelling funder relationships.
  • Errors & reference — every endpoint and the error contract.
  • Console — manage keys and namespaces, try endpoints in the Playground, and inspect what you loaded.