Skip to content

Mint the single-use pay link for the live balance of one of my bookings

POST
/account/obligations/{obligation_ref}/balance-links
curl --request POST \
--url https://quikstik-core.fly.dev/account/obligations/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/balance-links \
--header 'Authorization: Bearer <token>' \
--header 'Idempotency-Key: example'

Customer portal, guest-scoped (HANDOFF-account-self-serve-2026-10-18 WP3). local-person session; the obligation must be one the caller’s reach rule returns (buyer, rider, or head of a rider) — anything else is 404 obligation_not_found. This is the staff mint (POST /obligations/{obligation_ref}/balance-links) scoped to the signed-in person: same refusals (409 nothing_owed, obligation_not_open, idempotency_key_reused), same one-open-link supersession, the link stores no amount, and the page it opens reads the live balance. The portal redirects to url. A replay of the same Idempotency-Key is 200 with url: null (the plaintext token is not recoverable), so a button press should send a fresh key.

obligation_ref
required
string format: uuid
Idempotency-Key
required
string
>= 1 characters

Idempotency key for the command envelope. A retry with the same key is a no-op.

Replay of an earlier mint with the same key (no url)

Media typeapplication/json
object
link_id
required
string format: uuid
obligation_ref
required
string format: uuid
url

The pay page; present only on the minting call

string
nullable
expires_at
required
string format: date-time
status

Present on a replay

string
already_minted
required
boolean

Example generated

{
"link_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"obligation_ref": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"url": "example",
"expires_at": "2026-04-15T12:00:00Z",
"status": "example",
"already_minted": true
}

Minted

Media typeapplication/json
object
link_id
required
string format: uuid
obligation_ref
required
string format: uuid
url

The pay page; present only on the minting call

string
nullable
expires_at
required
string format: date-time
status

Present on a replay

string
already_minted
required
boolean

Example generated

{
"link_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"obligation_ref": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"url": "example",
"expires_at": "2026-04-15T12:00:00Z",
"status": "example",
"already_minted": true
}

Malformed body

Media typeapplication/json
object
reason
required
string

Example generated

{
"reason": "example"
}

Missing or invalid session bearer token

Media typeapplication/json
object
reason
required

Stable, machine-readable reason code (e.g. “sold_out”, “processor_not_configured”, “rail_refused”).

string

Example

{
"reason": "sold_out"
}

The session’s effect authority does not cover this operation

Media typeapplication/json
object
reason
required

Stable, machine-readable reason code (e.g. “sold_out”, “processor_not_configured”, “rail_refused”).

string

Example

{
"reason": "sold_out"
}

Expired, consumed, unknown, or unresolvable — indistinguishable by design

Media typeapplication/json
object
reason
required
string

Example generated

{
"reason": "example"
}

nothing_owed, obligation_not_open, or idempotency_key_reused

Media typeapplication/json
object
reason
required

Stable machine reason

string
detail

Finer machine code under reason

string
current
object
booking_id
required
string format: uuid
refund_minor
required

Minor units the card gets back

integer format: int64
refund_bps
required
integer
<= 10000
tier_hours

Hours-before-departure the applying tier requires; absent when no tier applies

integer
deadline_at

Last instant this refund still applies; absent when no tier applies

string format: date-time
currency
required
string

Example generated

{
"reason": "example",
"detail": "example",
"current": {
"booking_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"refund_minor": 1,
"refund_bps": 1,
"tier_hours": 1,
"deadline_at": "2026-04-15T12:00:00Z",
"currency": "example"
}
}

The command is rejected by a domain lifecycle gate (illegal state transition)

Media typeapplication/json
object
code
required

Stable machine-readable error code

string
message
required

Human-readable explanation (never leaks SQL, URLs, or secrets)

string

Example generated

{
"code": "example",
"message": "example"
}

No durable backend is wired for this operation (fail-closed)

Media typeapplication/json
object
reason
required

Stable, machine-readable reason code (e.g. “sold_out”, “processor_not_configured”, “rail_refused”).

string

Example

{
"reason": "sold_out"
}