Direct API integration¶
Use this mode when:
- Your product is not written in TypeScript / JavaScript (Python, Go, Ruby, .NET — all fine).
- You need custom HTTP behaviour (mTLS, custom retry, proxying through a corporate edge).
- You want to consume the API exactly as documented, with no SDK abstraction.
What you need¶
client_id+client_secret(from your platform operator)- The list of OAuth2 scopes you've been granted
- The platform host (e.g.
https://platform.example.com) — every service is reachable on the same host under a per-service path prefix (/v1/auth,/v1/clinical-api,/v1/orchestrator,/v1/ai-review,/v1/human-review,/v1/consent,/v1/user-management,/v1/notifications). The examples below show how to compose each endpoint.
Step 1 — get an access token¶
The platform uses standard OAuth2 client-credentials.
POST https://platform.example.com/v1/auth/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=<your-client-id>
&client_secret=<your-client-secret>
&scope=cases:write patients:write images:write
Response:
{
"access_token": "eyJhbGc...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "cases:write patients:write images:write"
}
Tokens are typically valid for ~1 hour. Cache the token in memory and re-issue on expiry (or 30s before, to absorb clock skew).
Step 2 — call an endpoint¶
Attach the token as a Bearer on every request:
curl -X POST https://platform.example.com/v1/clinical-api/cases \
-H "Authorization: Bearer eyJhbGc..." \
-H "Content-Type: application/json" \
-d '{"patient_id": "<patient-uuid>"}'
Step 3 — handle errors¶
- 401 — token expired or invalid. Re-issue.
- 403 — token lacks the scope for this endpoint. Check the catalogue in the Integration tab.
- 404 — resource not found (or you're trying to access an org you don't own).
- 409 — conflict (e.g. unique constraint violation).
- 4xx with
application/problem+json— RFC-7807 payload withtitle+detail+status. Useful for surfacing to your own UI. - 5xx — retry with jitter; the platform's read endpoints are idempotent, writes use a request-id-based dedupe on most paths.
Workflows¶
When your scopes include orchestrator:*, your integration can:
- Fetch a workflow definition —
GET /v1/orchestrator/workflow-definitions/:id. The response is the step graph (collect-questions, collect-images, decision, output) the platform uses to drive client-driven cases. - Fetch a workflow instance —
GET /v1/orchestrator/workflow-instances/:id. Returns the case's current state + the parked step (if any). - Advance the instance —
POST /v1/orchestrator/workflow-instances/:id/advancewith{ step_id, output }. Submits the answer/payload for the parked step and resumes execution.
See the Integration tab for the exact paths your scopes give you.
Reference¶
The Postman collection downloadable from the Integration tab is the easiest way to see every endpoint your scopes allow, complete with sample request bodies. Import → set client_secret variable → run the auth request → copy access_token into the accessToken variable → done.