---
title: "Revoke an affiliation"
method: POST
path: "/organizations/sub-orgs/revoke"
tags: ["Organizations"]
---

# Revoke an affiliation

`POST /organizations/sub-orgs/revoke`

## Request

- Base URL: `https://app.arkova.ai/api/v1`
- URL: `https://app.arkova.ai/api/v1/organizations/sub-orgs/revoke`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

Revoke the affiliation of an organization affiliated with the calling key's organization. Requires the orgs:manage scope. Revocation severs the affiliation; it does not reclaim credits or suspend the organization — use /offboard for that. Lifecycle: a child requests affiliation (dashboard) and becomes PENDING; approve moves PENDING to APPROVED; credits move only while the affiliate is APPROVED and not suspended; offboard reclaims the remaining credits and suspends the affiliate, in any status; revoke ends the relationship from APPROVED or PENDING. offboard then revoke and revoke then offboard are both supported - offboard never requires APPROVED and revoke never refuses a suspended affiliate. Counts against the API key monthly usage quota (no exemption exists for administration routes) and requires the organization payment state to be current.

## Request body

- object
  - `org_public_id` string, required: Public identifier of the affiliated organization. NOT the internal uuid — sending one returns 400 use_public_id.

## Response `200`

Affiliation revoked

- SubOrganizationStatus
  - `status` 'APPROVED' | 'REVOKED', required
  - `public_id` string, required

## Other responses

- `400`: Invalid request
- `401`: Authentication required
- `403`: Refused, named by a machine code in `error`: `insufficient_scope` (the key lacks orgs:manage), `acting_org_not_found` (the key's own organization no longer exists), or `sub_org_cannot_manage_sub_orgs` (the key belongs to an affiliated organization, which cannot administer affiliates of its own).
- `404`: No affiliated organization the caller may address answers to this public id. Deliberately indistinguishable from "belongs to another parent", "not approved yet" and "suspended" — this endpoint is not an existence oracle.
- `409`: A state conflict, named by a machine code in `error`: `already_revoked` or `affiliation_changed` (the affiliation moved under the request — re-read and retry). Also `409 ambiguous_caller`: the request presented both a verified session and an API key, and neither credential may be allowed to pick which organization is acting. Send exactly one.
- `422`: Request body failed validation
- `429`: Rate limit exceeded
- `500`: audit_write_failed — the affiliation status WAS changed and the audit row could not be written. The two are separate statements, so the change cannot be rolled back from here; the error names the audit write rather than pretending the action failed. A retry is safe and answers 409 already_approved / already_revoked.
- `502`: The underlying database function refused the call with a code this API version does not name. `error` carries that code verbatim. Not a 500: the request was answered, not dropped.
- `503`: A required lookup or RPC was unavailable, named by a machine code in `error`: `org_lookup_unavailable` (the acting-organization read failed), `sub_org_lookup_unavailable`, `sub_org_list_unavailable`, `rollup_projection_unavailable`, `credit_allocation_unavailable`, `credit_rollup_unavailable`, `balance_lookup_unavailable`, `suspend_unavailable`, `offboard_unavailable`, `cap_check_unavailable`, or `api_key_principal_unresolved` (the key is authorized but the principal it must stamp on the row could not be resolved). Never returned in place of a definitive answer.

---

[API](https://skmtc.dev/arkova/apis/arkova-verification-api.md) · [All operations](https://skmtc.dev/arkova/apis/arkova-verification-api/llms.txt) · [OpenAPI document](https://skmtc.dev/arkova/apis/arkova-verification-api/revisions/a14858d1efd4?raw)
