CAAB Partner API quickstart
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
| Status | Handling |
|---|---|
| 400 | Malformed payload, missing idempotency key, or unsupported field. Fix the request before retrying. |
| 401 | Invalid workload token or end-user assertion. Refresh tokens and ensure the user assertion is an access token. |
| 403 | Wrong binding or partner, missing scope, inactive mapping or boundary, or policy denial. |
| 409 | Stale If-Match, conflicting idempotency key, or invalid lifecycle transition. Refresh the resource version before retrying. |
| 428 | A required If-Match header is missing. |
| 429 | Binding rate or daily quota exceeded. Honor Retry-After and use bounded exponential backoff. |
| 5xx | Retry only idempotent operations with the same Idempotency-Key. |
Crittora CAAB
Govern which operations an AI agent, user, or API client can invoke, with signed policy integrity and runtime enforcement.
