Keepable docs
Sender API

Access delegation

Let one tenant act on behalf of another. Request access to a tenant, and accept or reject requests targeting yours.

Access delegation lets one tenant operate on behalf of another. A payroll provider that sends payslips for many employers, or a BPO that handles correspondence for several agencies, needs to act as those organisations: delegation is the consented, auditable way to grant that.

The model is a two-sided handshake: the would-be delegate requests access, and the target tenant accepts or rejects it. Nothing is granted unilaterally. All of this needs the access.write scope.

Request access

The requesting tenant asks for access to a target tenant_id:

curl https://api.keepable.co/access_requests \
  -H "Authorization: Bearer $KEEPABLE_TOKEN" \
  -H "Keepable-Version: 2026-05-24" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "tenant_id": "ten_01HXP" }'
201 Created
{ "request_id": "req_01HXP", "tenant_id": "ten_01HXP", "status": "pending" }

The new request's id is also returned in a keepable-request-id header and a Location header pointing at the created request. The request starts pending.

Track requests

Both sides can list requests, paginated:

You are the…EndpointReturns
RequesterGET /access_requests/clientRequests you have made.
TargetGET /access_requests/tenant/{tenant_id}Requests targeting your tenant.
curl "https://api.keepable.co/access_requests/client?limit=50" \
  -H "Authorization: Bearer $KEEPABLE_TOKEN" \
  -H "Keepable-Version: 2026-05-24"
200 OK
{
  "requests": [
    { "request_id": "req_01HXP", "tenant_id": "ten_01HXP", "status": "pending" }
  ],
  "next_token": null
}

Accept or reject

The target tenant responds to a pending request by id with a decision of accept or reject:

curl -X PUT https://api.keepable.co/access_requests/req_01HXP \
  -H "Authorization: Bearer $KEEPABLE_TOKEN" \
  -H "Keepable-Version: 2026-05-24" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "decision": "accept" }'

A recorded decision returns 204 No Content, moving the request to accepted or rejected. Once accepted, the requesting tenant can act on behalf of the target within the scope its own credential allows.

Delegation grants operational access between tenants; it does not widen your OAuth2 scopes. A delegate still needs, say, content.write on its own token to send on the target's behalf: access delegation decides which tenants you may act for, scopes decide what you may do.