Mint an organization credential
OWNER, and an enrolled second factor. This is the credential a SaaS puts in a server to register its own client companies by API. THE FLOOR IS NOT ADMIN, and not by symmetry with anything: every other act an ADMIN performs lands inside their own organization, whereas companies:manage can register a company under ANY RUC in Peru, and core.companies.ruc is unique platform-wide, so claiming one DENIES it to whoever controls it -- a third party with no account here. SUNAT publishes no ownership oracle, so migration 000053's answer is attribution rather than prevention: every act writes an ops.audit_events row in the same transaction. A control whose whole mechanism is 'we can say who did it' belongs to the rank that can be held answerable. THE SECOND FACTOR IS CHECKED IN SQL, on auth.users.mfa_enrolled_at, because the failure this act invites is a stolen session -- which is by construction a caller of the correct rank, and would make the audit row name somebody who did nothing. Enrolment is self-service, so this strands nobody. THE TOKEN IS IN THE 201 AND NOWHERE ELSE.
OWNER, and an enrolled second factor. This is the credential a SaaS puts in a server to register its own client companies by API. THE FLOOR IS NOT ADMIN, and not by symmetry with anything: every other act an ADMIN performs lands inside their own organization, whereas companies:manage can register a company under ANY RUC in Peru, and core.companies.ruc is unique platform-wide, so claiming one DENIES it to whoever controls it -- a third party with no account here. SUNAT publishes no ownership oracle, so migration 000053's answer is attribution rather than prevention: every act writes an ops.audit_events row in the same transaction. A control whose whole mechanism is 'we can say who did it' belongs to the rank that can be held answerable. THE SECOND FACTOR IS CHECKED IN SQL, on auth.users.mfa_enrolled_at, because the failure this act invites is a stolen session -- which is by construction a caller of the correct rank, and would make the audit row name somebody who did nothing. Enrolment is self-service, so this strands nobody. THE TOKEN IS IN THE 201 AND NOWHERE ELSE.
Authorization
consoleSession Set by POST /console/v1/sessions. HttpOnly, Secure, SameSite=Strict, Path=/, __Host- prefixed. It is never readable by JavaScript and there is no header alternative: accepting both carriers would let an attacker choose the weaker one.
In: cookie
Path Parameters
uuidRequest Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/console/v1/organizations/497f6eca-6276-4993-bfeb-53cbbbba6f08/credentials" \ -H "Authorization: Bearer apf_v2_tu_credencial" \ -H "Content-Type: application/json" \ -d '{ "name": "provisioning · staging", "scopes": [ "organizations:read" ], "expiresInDays": 90 }'{ "schemaVersion": "console.1", "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6", "credentialId": "f568fec0-10b6-4b94-9daf-e62c50c9bf3e", "token": "string", "name": "string", "organizationId": "7bc05553-4b68-44e8-b7bc-37be63c6d9e9", "organizationName": "string", "scopes": [ "string" ], "expiresAt": "2019-08-24T14:15:22Z", "createdAt": "2019-08-24T14:15:22Z", "auditEventId": "b284fbf1-1a7a-4799-bddc-ba227ef5747f"}The provisioning credentials of this organization GET GET
OWNER, and NOT VIEWER as the company credential listing is. That one is VIEWER because GET /console/v1/companies/{companyId}/activity already publishes every company credential's public prefix to every VIEWER, so hiding the list would be a rule with no content; nothing publishes an organization credential's prefix, because it issues nothing and so reaches no activity row. What is left is that this listing is the input to the revocation decision -- you revoke the row you are looking at -- and a list readable by somebody who cannot act on it splits an emergency across two people. It carries no secret: only a SHA-256 is stored. Revoked and expired credentials stay in it.
Revoke an organization credential DELETE DELETE
Immediate, not at expiry: auth.assert_organization_credential re-reads revoked_at on every provisioning statement. Same OWNER floor as minting, never higher, AND DELIBERATELY WITHOUT THE SECOND FACTOR the mint requires. Revocation is the emergency action -- it is what somebody does at 2am with a secret in a public repository -- and the person reaching for the kill switch is the person whose phone may be the thing that was lost. Minting creates risk and carries the friction; revoking removes risk and carries none. Unknown, already revoked, and belonging to another organization are one 404.