Skip to content
bucker

API reference

approval-requests

5 operations. Shapes are sketches of the declared schemas, bounded in depth — the authoritative document is linked from the index.

GET/orgs/{orgSlug}/approval-requests

Requires bearerAuth

Parameters

Parameters for GET /orgs/{orgSlug}/approval-requests
NameInTypeNotes
orgSlugrequiredpathstringmin length 1
statusquery"PENDING" | "APPROVED" | "REJECTED" | "EXPIRED"one of "PENDING" | "APPROVED" | "REJECTED" | "EXPIRED"
limitqueryintegerdefault 50, min 1, max 100

Response 200

{
  data: {
    id: string
    orgId: string
    requesterPrincipalId: string
    onBehalfOfPrincipalId: string | null
    action: string
    riskClass: string
    targetType: string
    targetId: string
    status: "PENDING" | "APPROVED" | "REJECTED" | "EXPIRED"
    minApprovers: integer
    policyId: string | null
    deciderPrincipalId: string | null
    decidedAt: string | null
    reason: string | null
    expiresAt: string
    createdAt: string
    payload: unknown | null
  }[]
}

Response 400 · `bad_request` — the path, query or body failed validation. `details` carries the Zod issues, one per offending field.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 401 · `unauthorized` — no credential, or one that is expired, revoked or not valid for this resource. `mfa_required` when the credential is good but a second factor is owed.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 403 · `forbidden` — the credential is valid and its scopes or this principal’s membership do not reach this resource. Scopes are re-intersected with live memberships on every request, so this can appear for a token that worked yesterday.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 404 · `not_found` — no such resource, OR one this principal cannot see. The two are deliberately one answer: a 403 would confirm the existence of something whose identifier is guessable.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 429 · `rate_limited` or `quota_exceeded` — over a ceiling. `Retry-After` says when to come back, and `x-ratelimit-limit` / `-remaining` / `-reset` describe the bucket.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 500 · `internal_error` — an unhandled failure on this side. The message is always generic; `requestId` is the part worth quoting.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Request

curl https://api.bucker.io/orgs/{orgSlug}/approval-requests \
  -H 'authorization: Bearer $BUCKER_TOKEN'

POST/orgs/{orgSlug}/approval-requests

Requires bearerAuth

Parameters

Parameters for POST /orgs/{orgSlug}/approval-requests
NameInTypeNotes
orgSlugrequiredpathstringmin length 1

Request body (required) · application/json

{
  action: string
  targetType: string
  targetId: string
  projectTag?: string | null
  summary?: string | null
  ttlMinutes?: integer
  channelIds?: string[]
  notify?: boolean
}

Response 200

{
  decision: "ALLOW" | "ASK" | "DENY"
  riskClass: string
  reason: string
  minApprovers: integer
  policySource: string
  request: {
    id: string
    orgId: string
    requesterPrincipalId: string
    onBehalfOfPrincipalId: string | null
    action: string
    riskClass: string
    targetType: string
    targetId: string
    status: "PENDING" | "APPROVED" | "REJECTED" | "EXPIRED"
    minApprovers: integer
    policyId: string | null
    deciderPrincipalId: string | null
    decidedAt: string | null
    reason: string | null
    expiresAt: string
    createdAt: string
    payload: unknown | null
  } | null
  deliveries: {
    channelId: string | null
    kind: string
    delivered: boolean
    error: string | null
  }[]
}

Response 201

{
  decision: "ALLOW" | "ASK" | "DENY"
  riskClass: string
  reason: string
  minApprovers: integer
  policySource: string
  request: {
    id: string
    orgId: string
    requesterPrincipalId: string
    onBehalfOfPrincipalId: string | null
    action: string
    riskClass: string
    targetType: string
    targetId: string
    status: "PENDING" | "APPROVED" | "REJECTED" | "EXPIRED"
    minApprovers: integer
    policyId: string | null
    deciderPrincipalId: string | null
    decidedAt: string | null
    reason: string | null
    expiresAt: string
    createdAt: string
    payload: unknown | null
  } | null
  deliveries: {
    channelId: string | null
    kind: string
    delivered: boolean
    error: string | null
  }[]
}

Response 400 · `bad_request` — the path, query or body failed validation. `details` carries the Zod issues, one per offending field.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 401 · `unauthorized` — no credential, or one that is expired, revoked or not valid for this resource. `mfa_required` when the credential is good but a second factor is owed.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 403 · `forbidden` — the credential is valid and its scopes or this principal’s membership do not reach this resource. Scopes are re-intersected with live memberships on every request, so this can appear for a token that worked yesterday.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 404 · `not_found` — no such resource, OR one this principal cannot see. The two are deliberately one answer: a 403 would confirm the existence of something whose identifier is guessable.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 429 · `rate_limited` or `quota_exceeded` — over a ceiling. `Retry-After` says when to come back, and `x-ratelimit-limit` / `-remaining` / `-reset` describe the bucket.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 500 · `internal_error` — an unhandled failure on this side. The message is always generic; `requestId` is the part worth quoting.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Request

curl -X POST https://api.bucker.io/orgs/{orgSlug}/approval-requests \
  -H 'authorization: Bearer $BUCKER_TOKEN' \
  -H 'content-type: application/json' \
  -d '{ … }'

GET/orgs/{orgSlug}/approval-requests/{requestId}

Requires bearerAuth

Parameters

Parameters for GET /orgs/{orgSlug}/approval-requests/{requestId}
NameInTypeNotes
orgSlugrequiredpathstringmin length 1
requestIdrequiredpathstringmin length 1

Response 200

{
  id: string
  orgId: string
  requesterPrincipalId: string
  onBehalfOfPrincipalId: string | null
  action: string
  riskClass: string
  targetType: string
  targetId: string
  status: "PENDING" | "APPROVED" | "REJECTED" | "EXPIRED"
  minApprovers: integer
  policyId: string | null
  deciderPrincipalId: string | null
  decidedAt: string | null
  reason: string | null
  expiresAt: string
  createdAt: string
  payload: unknown | null
}

Response 400 · `bad_request` — the path, query or body failed validation. `details` carries the Zod issues, one per offending field.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 401 · `unauthorized` — no credential, or one that is expired, revoked or not valid for this resource. `mfa_required` when the credential is good but a second factor is owed.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 403 · `forbidden` — the credential is valid and its scopes or this principal’s membership do not reach this resource. Scopes are re-intersected with live memberships on every request, so this can appear for a token that worked yesterday.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 404 · `not_found` — no such resource, OR one this principal cannot see. The two are deliberately one answer: a 403 would confirm the existence of something whose identifier is guessable.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 429 · `rate_limited` or `quota_exceeded` — over a ceiling. `Retry-After` says when to come back, and `x-ratelimit-limit` / `-remaining` / `-reset` describe the bucket.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 500 · `internal_error` — an unhandled failure on this side. The message is always generic; `requestId` is the part worth quoting.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Request

curl https://api.bucker.io/orgs/{orgSlug}/approval-requests/{requestId} \
  -H 'authorization: Bearer $BUCKER_TOKEN'

POST/orgs/{orgSlug}/approval-requests/{requestId}/approve

Requires bearerAuth

Parameters

Parameters for POST /orgs/{orgSlug}/approval-requests/{requestId}/approve
NameInTypeNotes
orgSlugrequiredpathstringmin length 1
requestIdrequiredpathstringmin length 1

Request body (required) · application/json

{
  reason?: string
} | null

Response 200

{
  request: {
    id: string
    orgId: string
    requesterPrincipalId: string
    onBehalfOfPrincipalId: string | null
    action: string
    riskClass: string
    targetType: string
    targetId: string
    status: "PENDING" | "APPROVED" | "REJECTED" | "EXPIRED"
    minApprovers: integer
    policyId: string | null
    deciderPrincipalId: string | null
    decidedAt: string | null
    reason: string | null
    expiresAt: string
    createdAt: string
    payload: unknown | null
  }
  approvals: integer
  remaining: integer
  hasIndependentApprover: boolean
  idempotent: boolean
}

Response 400 · `bad_request` — the path, query or body failed validation. `details` carries the Zod issues, one per offending field.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 401 · `unauthorized` — no credential, or one that is expired, revoked or not valid for this resource. `mfa_required` when the credential is good but a second factor is owed.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 403 · `forbidden` — the credential is valid and its scopes or this principal’s membership do not reach this resource. Scopes are re-intersected with live memberships on every request, so this can appear for a token that worked yesterday.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 404 · `not_found` — no such resource, OR one this principal cannot see. The two are deliberately one answer: a 403 would confirm the existence of something whose identifier is guessable.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 429 · `rate_limited` or `quota_exceeded` — over a ceiling. `Retry-After` says when to come back, and `x-ratelimit-limit` / `-remaining` / `-reset` describe the bucket.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 500 · `internal_error` — an unhandled failure on this side. The message is always generic; `requestId` is the part worth quoting.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Request

curl -X POST https://api.bucker.io/orgs/{orgSlug}/approval-requests/{requestId}/approve \
  -H 'authorization: Bearer $BUCKER_TOKEN' \
  -H 'content-type: application/json' \
  -d '{ … }'

POST/orgs/{orgSlug}/approval-requests/{requestId}/reject

Requires bearerAuth

Parameters

Parameters for POST /orgs/{orgSlug}/approval-requests/{requestId}/reject
NameInTypeNotes
orgSlugrequiredpathstringmin length 1
requestIdrequiredpathstringmin length 1

Request body (required) · application/json

{
  reason: string
}

Response 200

{
  request: {
    id: string
    orgId: string
    requesterPrincipalId: string
    onBehalfOfPrincipalId: string | null
    action: string
    riskClass: string
    targetType: string
    targetId: string
    status: "PENDING" | "APPROVED" | "REJECTED" | "EXPIRED"
    minApprovers: integer
    policyId: string | null
    deciderPrincipalId: string | null
    decidedAt: string | null
    reason: string | null
    expiresAt: string
    createdAt: string
    payload: unknown | null
  }
  approvals: integer
  remaining: integer
  hasIndependentApprover: boolean
  idempotent: boolean
}

Response 400 · `bad_request` — the path, query or body failed validation. `details` carries the Zod issues, one per offending field.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 401 · `unauthorized` — no credential, or one that is expired, revoked or not valid for this resource. `mfa_required` when the credential is good but a second factor is owed.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 403 · `forbidden` — the credential is valid and its scopes or this principal’s membership do not reach this resource. Scopes are re-intersected with live memberships on every request, so this can appear for a token that worked yesterday.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 404 · `not_found` — no such resource, OR one this principal cannot see. The two are deliberately one answer: a 403 would confirm the existence of something whose identifier is guessable.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 429 · `rate_limited` or `quota_exceeded` — over a ceiling. `Retry-After` says when to come back, and `x-ratelimit-limit` / `-remaining` / `-reset` describe the bucket.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Response 500 · `internal_error` — an unhandled failure on this side. The message is always generic; `requestId` is the part worth quoting.

{
  error: {
    code: "bad_request" | "conflict" | "forbidden" | "internal_error" | "mfa_required" | "not_found" | "payload_too_large" | "quota_exceeded" | … 6 more
    message: string
    details?: unknown
    requestId?: string
  }
}

Request

curl -X POST https://api.bucker.io/orgs/{orgSlug}/approval-requests/{requestId}/reject \
  -H 'authorization: Bearer $BUCKER_TOKEN' \
  -H 'content-type: application/json' \
  -d '{ … }'