Responses
How a human (or a delegate) settles an ask.
Generated from the contract, version 2.0.0-draft.2 (OpenAPI). Base URL https://usekabu.com/api. Errors are problem details, each code with its own page.
A human responds to an ask
POST/v2/messages/{message_id}/responsesCalled by the Kabu apps, by the answer page behind a delivered link, or by an integrator key with answers:delegate (recorded as delegated, with asserted_by). Any key holding messages:write gets 403 self_response_forbidden (test mode excepted), so an agent can never answer its own or a sibling’s ask. After settlement: 409 already_settled with the settled message; after the deadline: 410 ask_expired.
- Auth: an API key, or a signed-in human’s token (the Kabu apps).
- Scopes:
answers:delegate. - Refused to: a key holding
messages:write. - Signed-in humans:
audience.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
message_id |
path | string | Required | A msg_… id. |
Idempotency-Key |
header | string, at most 255 characters | Optional | Retry-safe key. For messages, sessions and responses it binds to the created object for its life; elsewhere for 24 h. |
Kabu-Org |
header | string | Optional | Select a live membership (default personal org); non-member is 404. Human tokens are live-only. Caller user id is distinct from billing owner. |
Request body: ResponseInput.
| Status | Means | Body |
|---|---|---|
200 |
Settled; the message with its resolution. | Message |
4XX |
Error | Problem |
5XX |
Error | Problem |
curl -X POST "https://usekabu.com/api/v2/messages/$MESSAGE_ID/responses" \
-H "Authorization: Bearer $KABU_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"decision":"approve"}'Mint a single-use answer link for one recipient
POST/v2/messages/{message_id}/answer_linksFor integrators who deliver asks through their own channels. Audited. A key holding messages:write gets 403 self_response_forbidden. Kabu-delivered links never appear in API bodies.
- Auth: an API key.
- Scopes:
answers:delegate. - Refused to: a key holding
messages:write.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
message_id |
path | string | Required | A msg_… id. |
Idempotency-Key |
header | string, at most 255 characters | Optional | Retry-safe key. For messages, sessions and responses it binds to the created object for its life; elsewhere for 24 h. |
Request body: AnswerLinkCreate.
| Status | Means | Body |
|---|---|---|
201 |
OK | AnswerLink |
4XX |
Error | Problem |
5XX |
Error | Problem |
curl -X POST "https://usekabu.com/api/v2/messages/$MESSAGE_ID/answer_links" \
-H "Authorization: Bearer $KABU_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"recipient":"…"}'Verify a receipt and return its claims
POST/v2/receipts/verifyFor integrators without a JWS library. Checks signature, issuer and that the receipt belongs to the caller’s org and mode; an invalid receipt is 422 invalid_receipt. Offline verification against /.well-known/jwks.json gives the same answer.
- Auth: an API key, or a signed-in human’s token (the Kabu apps).
- Scopes:
messages:read. - Signed-in humans:
audience.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
Kabu-Org |
header | string | Optional | Select a live membership (default personal org); non-member is 404. Human tokens are live-only. Caller user id is distinct from billing owner. |
Request body: ReceiptVerify.
| Status | Means | Body |
|---|---|---|
200 |
OK | ReceiptClaims |
4XX |
Error | Problem |
5XX |
Error | Problem |
curl -X POST "https://usekabu.com/api/v2/receipts/verify" \
-H "Authorization: Bearer $KABU_API_KEY" \
-H "Content-Type: application/json" \
-d '{"receipt":"…"}'Schemas
ResponseInput
Validated against the stored ask. as_recipient is required for delegated responses and ignored otherwise.
Type: ApproveInput or RejectInput or IgnoreInput or EditInput or RespondInput.
Chosen by decision: "approve": ApproveInput, "reject": RejectInput, "ignore": IgnoreInput, "edit": EditInput, "respond": RespondInput.
ApproveInput
option is required when the ask offers more than one approve option (e.g. once vs session).
| Property | Type | Required | Description |
|---|---|---|---|
decision |
"approve" |
Required | |
option |
string | Optional | |
comment |
string, at most 1000 characters | Optional | |
as_recipient |
RecipientRef | Optional | rcp_…, ext:<your external id>, or me (the key’s default_to). |
surface |
Surface | Optional | Records via for a user token only; never raises assurance. Links remain link, delegates delegated. Web BFF forces web. |
Unknown properties are refused.
Surface
Records via for a user token only; never raises assurance. Links remain link, delegates delegated. Web BFF forces web.
Type: string, one of "app", "lock_screen", "watch", "live_activity", "web".
RejectInput
| Property | Type | Required | Description |
|---|---|---|---|
decision |
"reject" |
Required | |
option |
string | Optional | |
comment |
string, at most 1000 characters | Optional | |
as_recipient |
RecipientRef | Optional | rcp_…, ext:<your external id>, or me (the key’s default_to). |
surface |
Surface | Optional | Records via for a user token only; never raises assurance. Links remain link, delegates delegated. Web BFF forces web. |
Unknown properties are refused.
IgnoreInput
| Property | Type | Required | Description |
|---|---|---|---|
decision |
"ignore" |
Required | |
option |
string | Required | |
comment |
string, at most 1000 characters | Optional | |
as_recipient |
RecipientRef | Optional | rcp_…, ext:<your external id>, or me (the key’s default_to). |
surface |
Surface | Optional | Records via for a user token only; never raises assurance. Links remain link, delegates delegated. Web BFF forces web. |
Unknown properties are refused.
EditInput
Only when the ask has action and allow_edit. A full replacement of action.args, validated against args_schema.
| Property | Type | Required | Description |
|---|---|---|---|
decision |
"edit" |
Required | |
edited_args |
object, at least 1 keys | Required | |
comment |
string, at most 1000 characters | Optional | |
as_recipient |
RecipientRef | Optional | rcp_…, ext:<your external id>, or me (the key’s default_to). |
surface |
Surface | Optional | Records via for a user token only; never raises assurance. Links remain link, delegates delegated. Web BFF forces web. |
Unknown properties are refused.
RespondInput
Exactly one of: option (single choice), options (multiple choice), text (text ask, or choice with allow_other), values (form). Anything else is 400.
| Property | Type | Required | Description |
|---|---|---|---|
decision |
"respond" |
Required | |
option |
string | Optional | |
options |
array of string, 1 to 12 items | Optional | |
text |
string, at most 4000 characters | Optional | |
values |
FormValues | Optional | |
confidence |
integer, from 1 to 5 | Optional | |
comment |
string, at most 1000 characters | Optional | |
as_recipient |
RecipientRef | Optional | rcp_…, ext:<your external id>, or me (the key’s default_to). |
surface |
Surface | Optional | Records via for a user token only; never raises assurance. Links remain link, delegates delegated. Web BFF forces web. |
Unknown properties are refused.
AnswerLinkCreate
| Property | Type | Required | Description |
|---|---|---|---|
recipient |
RecipientRef | Required | rcp_…, ext:<your external id>, or me (the key’s default_to). |
expires_in |
integer, from 60 to 86400 | Optional |
Unknown properties are refused.
AnswerLink
A single-use capability. Deliver it only to that recipient.
| Property | Type | Required | Description |
|---|---|---|---|
object |
"answer_link" |
Required | |
url |
string (uri) | Required | |
recipient |
string | Required | |
single_use |
boolean | Required | |
expires_at |
Timestamp | Required |
ReceiptVerify
| Property | Type | Required | Description |
|---|---|---|---|
receipt |
string, at most 8192 characters | Required |
Unknown properties are refused.
ReceiptClaims
The signed payload of Resolution.receipt. Kabu attests what it recorded: the proposal it delivered and the response it received, not pixels seen or downstream execution. Keys rotate yearly and remain in the JWKS for the audit period; alg must be ES256.
| Property | Type | Required | Description |
|---|---|---|---|
v |
"1" |
Required | |
iss |
string | Required | https://api.usekabu.com |
aud |
string | Required | The org id. Verifiers must check it. |
livemode |
boolean | Required | |
jti |
string | Required | Unique receipt id. |
iat |
integer | Required | |
msg |
string | Required | The message id. |
rev |
integer | Required | Request revision; always 1 (asks are immutable). |
req_digest |
string | Required | sha256 of RFC 8785 JSON of {org, livemode, msg, rev, title, body, blocks, links, attachments:[{media, sha256}], action, ask} with quiz.correct and all delivery state, URLs and receipts excluded. |
decision |
string | Required | |
value_digest |
string or null | Required | |
effective_action_digest |
string or null | Required | |
grant |
Grant or null | Required | |
sub |
string | Required | The responding human (rcp_…) or system. |
asserted_by |
string or null | Required | |
assurance |
string | Required | |
source |
string | Required | |
via |
string | Required | |
resolved_at |
integer | Required |