Permits (SignedPermit)
A SignedPermit is a cryptographically signed authorization for a specific action. The Brain & Permit principle: Axowl issues the permit; your plugin/app performs the action and verifies the permit. Base path: /api/org/{slug}/permits (authenticated).
| Method · Route | Purpose |
|---|---|
POST /issue | Issue a SignedPermit for the caller’s ConnectedId + requested scope |
Whose permit is it?
Section titled “Whose permit is it?”The permit is always issued for the caller’s own ConnectedId in the organization named by {slug} —
there is no way to request a permit on behalf of another badge. A person who belongs to several
organizations holds a separate badge in each; the one in the route’s organization is the one that counts.
Request body
Section titled “Request body”| Field | Type | Notes |
|---|---|---|
requestedScope | string, required | Scope key from the permission scopes catalog. |
ttlSeconds | int, optional (default 30) | 1–300. A value outside that range is refused with 400 and error: "invalid_ttl_seconds". |
idempotencyKey | string, optional | Replays the same permit within its TTL. Scoped to your badge and scope — your key cannot collide with another caller’s. |
context | object, optional | Free-form, embedded in the permit as a context claim. |
Issuance checks (in order)
Section titled “Issuance checks (in order)”POST /issue runs these before signing:
- Organization — resolve
{slug}; the caller must be a member (enforced upstream by tenant resolution). - Badge — resolve the caller’s
ConnectedIdin that organization. - Active — is the
ConnectedIdactive? - Revocation — is the
ConnectedIdon the revocation list? - Scope — does the member hold the requested scope (an active, unexpired grant)? A wildcard grant counts when it covers the request under the same rules as a permission check — a read-only wildcard does not cover a write action — and an Owner-only scope needs the Owner or a grant that names it explicitly.
- Seal tier — derived from the org’s
SecurityMode. - Sign — issue the permit, RS256-signed with the org’s signing key.
Failure shapes: 400 no organization context, or ttlSeconds out of range · 404 no badge for the caller in that organization ·
403 badge inactive, revoked, or missing the scope · 500 the org has no signing key
(Settings → Keys).
Response
Section titled “Response”{ "decision": "…", "reason": null, "permit": { "scope": "…", "actorConnectedId": "…", "sealTier": 0, "idempotencyKey": "…", "issuedAt": "…", "expiresAt": "…", "signature": "<RS256 JWT>" } }When the scope is missing the answer is 403 with decision: "Deny", the reason, and
permit: null.
The permit is verifiable by your side against the org’s published JWKS — no shared secret. Permits draw their authority from the same sealed RBAC snapshot as everything else — see Roles & permissions and Permission scopes.