Skip to content

Resource Scope Catalog API

The Resource Scope Catalog lets the owner of a registered resource define its own scopes — permissions that show up as individually-consentable items on the Rakomi consent screen, without waiting on a platform release. A resource with no registered scopes behaves exactly as it did before this API existed: nothing changes for existing integrations.

The canonical machine-readable spec is the API reference. What follows is a human guide; field-level shapes are authoritative in the OpenAPI document.

  • Resource — the audience your access tokens are minted for (an RFC 8707 resource indicator). You register scopes on a resource your tenant already owns. Resources are not self-service in this release — contact Rakomi to have a resource registered for your tenant.
  • Scope — a capability string (e.g. acme:calendar:read) that a client can request and a user can individually approve or refuse.
  • sensitivitynormal (default is the more restrictive elevated if you omit this field) or elevated. Only normal-sensitivity scopes are ever shown as individually-checkable items on the consent screen. An elevated scope’s authorization path is deliberately out-of-band — it never appears as a checkbox next to a routine sign-in.
  • status — every new registration starts under review and is not grantable until approved. A resource owner can list a pending scope; it is simply not yet grantable. There is no self-service approval endpoint in this release — approval is performed by Rakomi, and no API or dashboard action promotes a pending entry.
POST /v1/resources/{resourceId}/scopes
Content-Type: application/json
{
"scope_name": "acme:calendar:read",
"sensitivity": "normal",
"display_metadata": {
"kind": "locale_text",
"locale_text": {
"en": "Read your calendar events",
"pl": "Odczyt wydarzeń w kalendarzu",
"de": "Kalenderereignisse lesen",
"fr": "Lire les événements du calendrier",
"es": "Leer eventos del calendario"
}
}
}

Response 201: the created catalog entry.

{
"id": "",
"resource_id": "",
"scope_name": "acme:calendar:read",
"status": "pending_review",
"sensitivity": "normal",
"requires_platform_enable": false,
"display_metadata": { "kind": "locale_text", "locale_text": { "en": "", "pl": "", "de": "", "fr": "", "es": "" } },
"created_at": "",
"updated_at": ""
}
Section titled “display_metadata — two ways to supply consent-screen copy”

display_metadata is a closed, two-shape field. Pick the one that matches who is authoring the copy:

  • { "kind": "locale_text", "locale_text": { ... } } — you supply the copy yourself, one string per supported locale. All locales are required; a registration missing any one of them is rejected. Your text is shown in the language the end user’s screen is already in — Rakomi never translates, edits or corrects its meaning. Before storage, surrounding whitespace is trimmed, runs of whitespace are collapsed to a single space, and invisible, bidirectional and control characters are removed; a value that is empty after that removal is rejected. Each locale value is limited to 256 characters after normalisation, and the object is closed: an unrecognised locale key is rejected, never ignored.
  • { "kind": "i18n_key", "i18n_key": "consent.scopes.<name>" } — reserved for scopes whose copy is authored and translated by Rakomi itself. A key outside the consent.scopes.* namespace is rejected; this shape is not a way to point at arbitrary existing text.

For nearly every integrator, locale_text is the right choice — it is the only shape that lets you supply your own copy at all.

Errors:

  • 400 resource_scope_catalog/reserved_namespacescope_name collides with a Rakomi-reserved prefix (mcp:, rakomi:, sso:, agent:, or a bare protocol scope name).
  • 400 resource_scope_catalog/malformed_scope_name — shape or length violation.
  • 400 resource_scope_catalog/i18n_key_outside_namespace — an i18n_key outside consent.scopes.*.
  • 400 validation/invalid_request — the request body failed schema validation: a locale_text value is missing, blank, longer than 256 characters, or an unrecognised locale key was supplied.
  • 400 resource_scope_catalog/locale_text_invalid — a locale_text value became empty after invisible, bidirectional and control characters were removed.
  • 400 resource_scope_catalog/resource_cap_exceeded — this resource is at its scope-count limit.
  • 400 resource_scope_catalog/tenant_aggregate_cap_exceeded — your tenant is at its aggregate limit across every resource it owns.
  • 403 resource_scope_catalog/platform_resource_immutable — you may not modify the platform’s own resource through this API.
  • 404 resource_scope_catalog/resource_not_found — unknown or not-owned resourceId (distinct from resource_scope_catalog/not_found, which refers to a missing catalog entry).
  • 409 resource_scope_catalog/duplicate — that scope name is already registered on this resource.
GET /v1/resources/{resourceId}/scopes

Returns the scopes registered on the resource, including ones still under review.

Response 200:

{
"data": [ /* catalog entries, same shape as the 201 above */ ],
"pagination": { "next_cursor": null, "has_more": false }
}

The response is always an envelope, never a bare array. Honour has_more / next_cursor even though the current implementation returns a single page. An unknown or not-owned resourceId yields a 200 with an empty data array — not a 404.

DELETE /v1/resources/{resourceId}/scopes/{id}

Response 204. Removing a scope is itself the full revocation for any future token mint; it does not retroactively touch tokens already issued.

Errors:

  • 404 resource_scope_catalog/not_found — no catalog entry with that id on that resource.
  • 403 resource_scope_catalog/platform_resource_immutable — you may not modify the platform’s own resource through this API.

Once a scope is approved and a client requests it, normal-sensitivity scopes render as individually checkable items on the Rakomi consent screen, alongside the platform’s own permissions — clearly labelled as defined by the resource, not by Rakomi and not necessarily by the requesting application. The user can tick some, all, or none of them; nothing here is all-or-nothing. The full record of what was shown and what was approved is retained for accountability regardless of how the screen summarized it.