API reference TEE
Countersign a cart
POST/v1/countersign
Sends the cart to the TEE legs in order and returns the countersignatures only when both agree. A DENY is countersigned too. An app acting for a user (purchases:write) countersigns only under a mandate that user approved for it; under a mandate of Keelson's hosted operator it sends mandateId and Keelson closes the mandate with that operator's key over the request id and this cart, and nothing else. A cart is bought once per mandate: while a purchase of the same cart is in flight, or for ten minutes after it was captured, another request for it is answered 409 purchase-exists with that purchase's id, whatever its request id, evidence or Idempotency-Key. Retrying after a lost answer is therefore safe; to buy the same cart again on purpose, name that purchase in repeatOf.
Headers
Content-Typeapplication/jsonRequiredidempotency-keystringRequiredIdempotency-KeystringRequired- 1 to 255 characters. A retry with the same key returns the first answer.
Request body
application/json
authorizationIdstring- The PayPal authorization that holds the mandate's funds, or this request's own hold when the mandate holds each purchase separately; leg A reads it. Absent for a card mandate, whose purchase is paid with a single-use card issued after the ALLOW.
closedMandatestring- The open mandate closed by the agent's key binding over the request and cart. Required, except of an app acting for a user under a mandate of Keelson's hosted operator, which sends
mandateIdinstead. mandateIdstring- Only for an app acting for a user (
purchases:write) under a mandate of Keelson's hosted operator that the user approved for it: Keelson closes the mandate with the hosted operator's key overrequestIdand this cart. requestIdstring- With
mandateId: the request ULID the closed mandate binds, and the purchase's id; a new one when left out. cartobjectRequiredunitobjectRequired- The PayPal purchase unit the cart is checked against:
{amount}, the checkout total the buyer pays as a PayPal Orders v2 amount, whosebreakdownhas theitem_totalof the cart's lines and, when the checkout charges them,tax_total,shippinganddiscount. Keelson countersignsamount.value, which must beitem_total + tax_total + shipping − discount, and checks it against the mandate's budget.handling,insuranceandshipping_discountare refused: fold them intoshipping. evidenceobject- Evidence sources per field.
channel3:sources are refused here: the API adds them from the observation stored in the evidence. evidenceRootstringRequired- The root of the evidence stored with
POST /v1/evidencefor this mandate. liveobject- Only when the buyer pays at the store's own checkout with their own PayPal account: Keelson countersigns and logs the purchase and issues its Alibi, and neither covers nor captures it. Its Alibi is public once the PayPal transaction is recorded. The agent's pay click waits for an ALLOW; the agent then records PayPal's transaction id with
PUT /v1/purchases/{id}/paypal-transaction. repeatOfstring- Only when the user asked to buy the same cart again: the id of the latest purchase of this cart under the mandate. Not needed once that purchase was denied or failed before capture, or was captured more than ten minutes ago. A retry after a lost answer never sends it: the
409 purchase-existsanswer names the purchase already made.
Responses
- 200The decision and its countersignatures
- 202Countersigned, and a step of the purchase is still pending;
Locationis the purchase, which finishes on its own - 401A leg refused the agent's authority
- 404No such mandate of an operator this client linked, or that the user approved for this app
- 409The mandate is not active, the evidence root is not stored for it or already binds another purchase, the request was already used, or the same cart is already being bought (
purchase-exists, with itspurchaseId) - 413A leg refused the request as too large
- 422The request is invalid, the purchase unit's amount does not reconcile with the cart (
invalid-amount), the authorization is not this purchase's hold, the cart is not the one held for this request, the evidence holds another cart or another checkout amount or reference rates Keelson did not issue, its Channel3 observation is not usable, its WebFact is not this purchase's, or a live store is not the website the mandate allows - 429Too many countersigns for this mandate
- 502The legs disagree, or a signer is not registered
- 503A leg needed to sign, or PayPal, is unavailable, or the hosted operator's key is not configured
200 response
purchaseIdstringRequiredmodestringRequireddegradedwhen leg B was unreachable and only leg A signed.One of2of2degradeddecisionstringRequired- One of
allowdeny countersignobjectRequired- The EIP-712
Countersignmessage, as decimal strings. digeststringRequiredsignaturesobjectRequiredsignersobjectRequiredtracevalue- The
keelson.eval/1trace both legs signed over. approvalobject- On a deny for a cart over the mandate's amount or outside its merchants: the user was asked to approve this cart once. Poll
POST /v1/connections/tokenwith itsdevice_code; the answer is a single-purchase mandate for exactly this cart. statestringCAPTUREDonce logged, covered and captured;FAILEDwithfailurewhen a step refused;COUNTERSIGNED,LOGGEDorCOVEREDwhile a step is pending;DENIEDfor a DENY.logIndexstring- The leaf's index in the Alibi log.
coverageobject- The
lockCoveragetransaction of the operator's bond. captureobject- The PayPal capture of the countersigned amount.
failureobject- The step that failed and why; nothing was captured.
blockedarray of string- For a
DENIEDcart, the mandate fields whose check failed. reasonsarray of object- For a
DENIEDcart, each failed field with what the mandate allowed and what the cart had, as text. checksarray of object- For a purchase the engine checked, each mandate field with what the mandate allowed, what the cart had and whether it held.
cardobject- A card purchase: its single-use card (never its number) and every authorization the card network sent it, with both legs' decision.
CAPTUREDonce the merchant's capture settles. liveobject- A purchase the buyer pays at the store's own checkout: the store's origin and the PayPal transaction id once the agent recorded it. Never covered nor captured.