Set a scope's policy document (new version; the old one retires)
const url = 'https://quikstik-core.fly.dev/policies/tenant/example';const options = { method: 'PUT', headers: { 'x-tenant-id': '2489E9AD-2EE2-8E00-8EC9-32D5F69181C0', Authorization: 'Bearer <token>', 'Content-Type': 'application/json' }, body: '{"cancel":{"tiers":[{"min_hours_before":1,"refund_bps":1}],"below":{"kind":"refund_all","bps":1,"fee":{"kind":"none","minor":1,"currency":"USD","bps":1}}},"reschedule":{"tiers":[{"min_hours_before":1,"outcome":{"kind":"refund_all","bps":1,"fee":{"kind":"none","minor":1,"currency":"USD","bps":1}}}],"below":{"kind":"refund_all","bps":1,"fee":{"kind":"none","minor":1,"currency":"USD","bps":1}}},"fee":{"kind":"none","minor":1,"currency":"USD","bps":1},"refund_as":{"kind":"money","expires_days":1},"weather":{"kind":"none","decision_hour_local":1,"forecast_source":"example","rain_chance_bps":1,"fraction_of_ride_bps":1,"outcome":"full_refund_or_rebook"},"no_show":{"kind":"refund_all","bps":1,"fee":{"kind":"none","minor":1,"currency":"USD","bps":1}},"overrides":{"waiver_reasons":["hardship"]},"text":{"summary_short":"example","summary_multi_day":"example"},"governs":true}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request PUT \ --url https://quikstik-core.fly.dev/policies/tenant/example \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --header 'x-tenant-id: 2489E9AD-2EE2-8E00-8EC9-32D5F69181C0' \ --data '{ "cancel": { "tiers": [ { "min_hours_before": 1, "refund_bps": 1 } ], "below": { "kind": "refund_all", "bps": 1, "fee": { "kind": "none", "minor": 1, "currency": "USD", "bps": 1 } } }, "reschedule": { "tiers": [ { "min_hours_before": 1, "outcome": { "kind": "refund_all", "bps": 1, "fee": { "kind": "none", "minor": 1, "currency": "USD", "bps": 1 } } } ], "below": { "kind": "refund_all", "bps": 1, "fee": { "kind": "none", "minor": 1, "currency": "USD", "bps": 1 } } }, "fee": { "kind": "none", "minor": 1, "currency": "USD", "bps": 1 }, "refund_as": { "kind": "money", "expires_days": 1 }, "weather": { "kind": "none", "decision_hour_local": 1, "forecast_source": "example", "rain_chance_bps": 1, "fraction_of_ride_bps": 1, "outcome": "full_refund_or_rebook" }, "no_show": { "kind": "refund_all", "bps": 1, "fee": { "kind": "none", "minor": 1, "currency": "USD", "bps": 1 } }, "overrides": { "waiver_reasons": [ "hardship" ] }, "text": { "summary_short": "example", "summary_multi_day": "example" }, "governs": true }'Auth: a staff session, or an operator key scoped policies.write (underwritten only by an
Admin/Owner membership; the audit actor is the key’s actor id) — a key without the scope is
403 insufficient_scope, an unknown or publishable key 401. scope_ref is - for tenant, an offering or variant uuid for
offering/variant, and a channel key for channel. The body is a partial policy: every rule
is optional and anything unset inherits. operator_cancel is fixed at refund_all and a
document that tries to set it is refused. A channel document applies only when it says
governs: true. Bookings made from now on snapshot the new terms; existing bookings keep
theirs.
422 carries reasons — stable codes such as operator_cancel_not_configurable,
bps_over_hundred_percent, outcome_not_executable, governs_only_on_channel,
channel_document_must_govern, duplicate_waiver_reason, malformed_document (with
detail) — and a bad scope is invalid_scope_kind / invalid_scope_ref. An audit event is
written in the same transaction.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Header Parameters
Section titled “Header Parameters”Tenant identifier (UUID).
Authn/authz semantics are intentionally TBD for this contract slice; this header exists to keep the contract explicitly multi-tenant from day 0.
Request Bodyrequired
Section titled “Request Bodyrequired”A scope’s partial policy: every rule optional, absent = inherit. operator_cancel is not settable (the server refuses a document that names it). governs is for channel scope only.
object
Tiers are most-notice-first; the most generous qualifying tier applies, else below.
object
object
One rule’s verdict. For a cancel, refund_all/no_refund/refund are the refund fraction; for a reschedule refund_all means a free change and no_refund means not allowed. ota_governed is produced by resolution for a booking whose channel governs it and is never stored in a document. refund carries bps; fee carries fee.
object
none as the inner fee of a fee outcome means “use the policy’s own fee”. flat carries minor + currency; percent carries bps; keep_deposit carries nothing.
object
object
object
One rule’s verdict. For a cancel, refund_all/no_refund/refund are the refund fraction; for a reschedule refund_all means a free change and no_refund means not allowed. ota_governed is produced by resolution for a booking whose channel governs it and is never stored in a document. refund carries bps; fee carries fee.
object
none as the inner fee of a fee outcome means “use the policy’s own fee”. flat carries minor + currency; percent carries bps; keep_deposit carries nothing.
object
One rule’s verdict. For a cancel, refund_all/no_refund/refund are the refund fraction; for a reschedule refund_all means a free change and no_refund means not allowed. ota_governed is produced by resolution for a booking whose channel governs it and is never stored in a document. refund carries bps; fee carries fee.
object
none as the inner fee of a fee outcome means “use the policy’s own fee”. flat carries minor + currency; percent carries bps; keep_deposit carries nothing.
object
none as the inner fee of a fee outcome means “use the policy’s own fee”. flat carries minor + currency; percent carries bps; keep_deposit carries nothing.
object
object
object
One rule’s verdict. For a cancel, refund_all/no_refund/refund are the refund fraction; for a reschedule refund_all means a free change and no_refund means not allowed. ota_governed is produced by resolution for a booking whose channel governs it and is never stored in a document. refund carries bps; fee carries fee.
object
none as the inner fee of a fee outcome means “use the policy’s own fee”. flat carries minor + currency; percent carries bps; keep_deposit carries nothing.
object
object
Rendering hints only; the full page renders from the rules.
object
Responses
Section titled “Responses”Stored as the scope’s next version
object
Example
{ "scope_kind": "tenant"}Invalid document or scope.
object
Example generated
{ "reason": "example", "reasons": [ "example" ], "detail": "example"}No durable backend is wired for this operation (fail-closed)
object
Stable, machine-readable reason code (e.g. “sold_out”, “processor_not_configured”, “rail_refused”).
Example
{ "reason": "sold_out"}