POST /v1/agent-cards/grants
Allow one card to be disclosed to an agent. Signed-in users only — a request authenticated with an API key is refused, because an agent that could grant itself access would make the allowlist meaningless.
POST
/v1/agent-cards/grants
Allow one card to be disclosed to an agent. Signed-in users only — a request
authenticated with an API key is refused, because an agent that could grant itself
access would make the allowlist meaningless.
Request Body required
Grant details
application/jsonOne of:
Option 1
Option 2
cardId
string
REQUIRED
CardID is the Airwallex card this grant allows to be disclosed. At most 255 characters,
the width of the column that stores it; a longer value is refused as a 400 rather than
reaching Postgres.
connectorId
string
REQUIRED
ConnectorID names the Airwallex account holding the card. Required: redeeming the grant
needs it, and a grant that cannot be redeemed must not be creatable. At most 255
characters, the width of the column that stores it.
maxUses
integer
MaxUses is the ceiling on how many handles this grant may ever mint — a grant is not a
standing licence to read a card. 1 to 1000; at or below zero is floored to 1.
note
string
Note is free text shown alongside the grant. At most 1000 characters.
ttlMinutes
integer
TTLMinutes is how long the grant stays valid. No bound is enforced here: a value outside
1 minute to 30 days is clamped to the 30-day maximum.
Responses
200
OK
application/jsoncode
integer
data
object
approvedAt
string
cardId
string
connectorId
string
createdAt
string
expiresAt
string
grantedBy
string
id
string
maxUses
integer
note
string
organizationId
string
purpose
string
requestedBy
string
retiredAt
string
RetiredAt exists for the unique index, not for the domain. idx_agent_card_grants_live
keeps one live grant per card, but a partial index predicate cannot reference now(),
so expiry is stamped here instead and the index excludes it. Only ever set on a row
that is already past ExpiresAt, and never by a human — a human withdrawing permission
sets RevokedAt, which redeem and the UI both read and this column deliberately is not.
revokedAt
string
updatedAt
string
uses
integer
message
string
requestId
string
400
Bad Request
403
Forbidden
409
Conflict
curl -X POST 'https://api.example.com/v1/agent-cards/grants' \ -H 'Authorization: Bearer YOUR_API_TOKEN' \ -H 'Content-Type: application/json' \ -d '{}'
const response = await fetch('https://api.example.com/v1/agent-cards/grants', { method: 'POST', headers: { "Authorization": "Bearer YOUR_API_TOKEN", "Content-Type": "application/json" }, body: JSON.stringify({})});const data = await response.json();console.log(data);
import requestsheaders = { 'Authorization': 'Bearer YOUR_API_TOKEN'}response = requests.post('https://api.example.com/v1/agent-cards/grants', headers=headers, json={})print(response.json())
package mainimport ( "fmt" "io" "net/http" "strings")func main() { body := strings.NewReader(`{}`) req, _ := http.NewRequest("POST", "https://api.example.com/v1/agent-cards/grants", body) req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN") req.Header.Set("Content-Type", "application/json") resp, _ := http.DefaultClient.Do(req) defer resp.Body.Close() result, _ := io.ReadAll(resp.Body) fmt.Println(string(result))}
200
Response
{ "code": 200, "data": { "approvedAt": "<string>", "cardId": "<string>", "connectorId": "<string>", "createdAt": "<string>", "expiresAt": "<string>", "grantedBy": "<string>", "id": "<string>", "maxUses": 123, "note": "<string>", "organizationId": "<string>", "purpose": "<string>", "requestedBy": "<string>", "retiredAt": "<string>", "revokedAt": "<string>", "updatedAt": "<string>", "uses": 123 }, "message": "success", "requestId": "abc-123"}
API Playground
Try this endpoint
POST
/v1/agent-cards/grants
