Crittora Logo
Getting StartedChangelogContact Support

CAAB Partner API quickstart

Audience: Partner backend and MCP developers
Contract: CAAB Partner API v1
Last verified against CAAB contract: August 4, 2026

Use this flow to complete one sandbox governed invocation from a partner-hosted application or MCP server. CAAB derives tenant and binding identity from the workload token; callers cannot select a partner or CAAB subject by payload.

Set environment variables

1export CAAB_API_BASE="https://<caab-api-host>/Prod"
2export CAAB_TOKEN_URL="https://<caab-cognito-domain>/oauth2/token"
3export CAAB_CLIENT_ID="<binding-workload-client-id>"
4export CAAB_CLIENT_SECRET="<binding-workload-client-secret>"
5export CAAB_BINDING_ID="<binding-id>"
Before running the flow
  • Store the workload client secret in a server-side secret manager.
  • Keep browser code, MCP tool arguments, logs, invitations, and OpenAPI documents free of live credentials.
  • Use the binding ID issued for the workload client; a different URL binding does not grant access.

1. Request a workload token

Request only scopes approved for the binding. Cognito access tokens expose the deployed resource-server form, for example caab/caab.partner.subjects.write.

1CAAB_WORKLOAD_TOKEN="$(curl --fail --silent \
2  --user "${CAAB_CLIENT_ID}:${CAAB_CLIENT_SECRET}" \
3  --data-urlencode 'grant_type=client_credentials' \
4  --data-urlencode 'scope=caab/caab.partner.subjects.write caab/caab.partner.apis.write caab/caab.partner.auth-profiles.write caab/caab.partner.templates.write caab/caab.permission-boundary.instantiate caab/caab.permission-boundary.read caab/caab.permission-boundary.revoke caab/caab.broker.execute caab/caab.partner.audit.read caab/caab.partner.diagnostics.read' \
5  "${CAAB_TOKEN_URL}" | jq -r '.access_token')"

2. Register an external subject

Use the immutable subject claim from the partner identity provider. The returned CAAB subject is credential-free and uses platform service policy crypto; it has no CAAB password or per-user Crittora credential.

1export EXTERNAL_SUBJECT="<immutable-oidc-sub>"
2
3curl --fail --request PUT \
4  --header "Authorization: Bearer ${CAAB_WORKLOAD_TOKEN}" \
5  --header 'Content-Type: application/json' \
6  --header 'Idempotency-Key: subject-<stable-operation-id>' \
7  --data '{"email":"user@example.org","displayName":"Example User","identityProvider":"partner_oidc"}' \
8  "${CAAB_API_BASE}/v1/bindings/${CAAB_BINDING_ID}/external-subjects/${EXTERNAL_SUBJECT}"

3. Preview and import OpenAPI

Preview first, then import the reviewed document. API revisions use both Idempotency-Key and If-Match; stale versions are rejected with a conflict response.

1jq -n --slurpfile document ./openapi.json '{document:$document[0]}' > /tmp/caab-api-import.json
2
3curl --fail --request POST \
4  --header "Authorization: Bearer ${CAAB_WORKLOAD_TOKEN}" \
5  --header 'Content-Type: application/json' \
6  --header 'Idempotency-Key: api-preview-<stable-operation-id>' \
7  --data @/tmp/caab-api-import.json \
8  "${CAAB_API_BASE}/v1/bindings/${CAAB_BINDING_ID}/apis/preview"
9
10curl --fail --request POST \
11  --header "Authorization: Bearer ${CAAB_WORKLOAD_TOKEN}" \
12  --header 'Content-Type: application/json' \
13  --header 'Idempotency-Key: api-import-<stable-operation-id>' \
14  --data @/tmp/caab-api-import.json \
15  "${CAAB_API_BASE}/v1/bindings/${CAAB_BINDING_ID}/apis"

4. Create a write-only auth profile

Auth-profile writes accept downstream secrets. Later reads return only redacted metadata such as presence indicators, header names, and versions.

1export API_ID="<imported-api-id>"
2export PROFILE_ID="production"
3
4curl --fail --request PUT \
5  --header "Authorization: Bearer ${CAAB_WORKLOAD_TOKEN}" \
6  --header 'Content-Type: application/json' \
7  --header 'Idempotency-Key: auth-profile-<stable-operation-id>' \
8  --header 'If-Match: "0"' \
9  --data '{
10    "mode":"oauth2_client_credentials",
11    "token_url":"https://vendor.example.com/oauth/token",
12    "client_auth_method":"client_secret_basic",
13    "client_id":"<vendor-client-id>",
14    "client_secret":"<vendor-client-secret>",
15    "scopes":["vendor.read"]
16  }' \
17  "${CAAB_API_BASE}/v1/bindings/${CAAB_BINDING_ID}/auth-profiles/${API_ID}/${PROFILE_ID}"

5. Create and assign a boundary

Templates hold the approved least-privilege shape. Instantiating a boundary signs and encrypts the policy for one external subject.

1curl --fail --request POST \
2  --header "Authorization: Bearer ${CAAB_WORKLOAD_TOKEN}" \
3  --header 'Content-Type: application/json' \
4  --header 'Idempotency-Key: template-<stable-operation-id>' \
5  --data '{
6    "templateId":"tenant-admin-readonly",
7    "name":"Tenant admin read only",
8    "capabilityId":"<capability-id>",
9    "allowedPermissionIds":["<permission-id>"],
10    "authProfileRef":"<capability-id>:oauth2_client_credentials:production"
11  }' \
12  "${CAAB_API_BASE}/v1/bindings/${CAAB_BINDING_ID}/permission-boundary-templates"
13
14curl --fail --request PUT \
15  --header "Authorization: Bearer ${CAAB_WORKLOAD_TOKEN}" \
16  --header 'Content-Type: application/json' \
17  --header 'Idempotency-Key: boundary-<stable-operation-id>' \
18  --data '{"templateId":"tenant-admin-readonly"}' \
19  "${CAAB_API_BASE}/v1/bindings/${CAAB_BINDING_ID}/subjects/${EXTERNAL_SUBJECT}/permission-boundary"

6. Invoke a governed operation

CAAB resolves the subject from the partner access token, verifies the protected policy, checks the permission on every call, injects the downstream auth profile, applies response redaction, and records evidence.

1export END_USER_ACCESS_TOKEN="<short-lived-partner-access-token>"
2
3curl --fail --request POST \
4  --header "Authorization: Bearer ${CAAB_WORKLOAD_TOKEN}" \
5  --header "X-CAAB-User-Assertion: ${END_USER_ACCESS_TOKEN}" \
6  --header 'Content-Type: application/json' \
7  --data '{
8    "permissionId":"<permission-id>",
9    "arguments":{},
10    "purpose":"User requested the approved operation"
11  }' \
12  "${CAAB_API_BASE}/v1/bindings/${CAAB_BINDING_ID}/invoke"

7. Read audit and diagnostics

1curl --fail --header "Authorization: Bearer ${CAAB_WORKLOAD_TOKEN}" \
2  "${CAAB_API_BASE}/v1/bindings/${CAAB_BINDING_ID}/subjects/${EXTERNAL_SUBJECT}/permission-boundary"
3
4curl --fail --header "Authorization: Bearer ${CAAB_WORKLOAD_TOKEN}" \
5  "${CAAB_API_BASE}/v1/bindings/${CAAB_BINDING_ID}/audit?limit=50"
6
7curl --fail --header "Authorization: Bearer ${CAAB_WORKLOAD_TOKEN}" \
8  "${CAAB_API_BASE}/v1/bindings/${CAAB_BINDING_ID}/diagnostics"

Collection responses use opaque nextCursor values. Pass the value back as cursor without decoding or constructing it.

8. Revoke the boundary

1curl --fail --request DELETE \
2  --header "Authorization: Bearer ${CAAB_WORKLOAD_TOKEN}" \
3  --header 'Idempotency-Key: boundary-revoke-<stable-operation-id>' \
4  "${CAAB_API_BASE}/v1/bindings/${CAAB_BINDING_ID}/subjects/${EXTERNAL_SUBJECT}/permission-boundary"

Retry and error rules

StatusHandling
400Malformed payload, missing idempotency key, or unsupported field. Fix the request before retrying.
401Invalid workload token or end-user assertion. Refresh tokens and ensure the user assertion is an access token.
403Wrong binding or partner, missing scope, inactive mapping or boundary, or policy denial.
409Stale If-Match, conflicting idempotency key, or invalid lifecycle transition. Refresh the resource version before retrying.
428A required If-Match header is missing.
429Binding rate or daily quota exceeded. Honor Retry-After and use bounded exponential backoff.
5xxRetry only idempotent operations with the same Idempotency-Key.

Next: browse the complete Partner API reference

Crittora CAAB

Govern which operations an AI agent, user, or API client can invoke, with signed policy integrity and runtime enforcement.

Least privilege
Runtime enforced
Auditable

Powered by AWS • Partner Technology • Patent Pending PQC Technology