{"ok":true,"data":{"contract":"v1","auth":{"kind":"bearer-token","header":"Authorization: Bearer <api-key>","hint":"Get a sandbox key at https://enfinitos.com/apply (sandbox intent), then exchange it for a v1 API key at https://enfinitos.com/developers/playground."},"routes":[{"method":"GET","path":"/v1","description":"Contract probe — surface this list.","scopes":[]},{"method":"GET","path":"/v1/healthz","description":"Operator health probe. Returns the live provider mode bindings.","scopes":[]},{"method":"GET","path":"/v1/tenant","description":"Read the caller's sandbox tenant snapshot.","scopes":["rights:read"]},{"method":"POST","path":"/v1/tenant/reset","description":"Wipe the caller's tenant and re-provision empty.","scopes":["rights:write"]},{"method":"GET","path":"/v1/rights","description":"List rights. Filters: status, substrate, cursor, limit.","scopes":["rights:read"]},{"method":"GET","path":"/v1/rights/{rightId}","description":"Fetch a single right + its provenance chain.","scopes":["rights:read"]},{"method":"GET","path":"/v1/rights/bases","description":"List bases.","scopes":["rights:read"]},{"method":"POST","path":"/v1/rights/bases","description":"Register a new basis.","scopes":["rights:write"]},{"method":"POST","path":"/v1/rights/issue","description":"Issue a new root right against a basis.","scopes":["rights:write"]},{"method":"POST","path":"/v1/rights/{rightId}/suspend","description":"Suspend an ACTIVE right.","scopes":["rights:write"]},{"method":"POST","path":"/v1/rights/{rightId}/resume","description":"Resume a SUSPENDED right.","scopes":["rights:write"]},{"method":"POST","path":"/v1/rights/{rightId}/revoke","description":"Revoke an ACTIVE or SUSPENDED right (terminal).","scopes":["rights:write"]},{"method":"GET","path":"/v1/offers","description":"List offers.","scopes":["offers:read"]},{"method":"POST","path":"/v1/offers/propose","description":"Propose a new offer against one of your rights.","scopes":["offers:write"]},{"method":"POST","path":"/v1/offers/{offerId}/accept","description":"Accept a PROPOSED offer; issues a derived right.","scopes":["offers:write"]},{"method":"POST","path":"/v1/offers/{offerId}/reject","description":"Reject a PROPOSED or COUNTERED offer.","scopes":["offers:write"]},{"method":"POST","path":"/v1/offers/{offerId}/counter","description":"Counter an offer with revised scope/terms.","scopes":["offers:write"]},{"method":"POST","path":"/v1/offers/{offerId}/withdraw","description":"Withdraw an offer you proposed.","scopes":["offers:write"]},{"method":"GET","path":"/v1/challenges","description":"List challenges.","scopes":["challenges:read"]},{"method":"POST","path":"/v1/challenges/open","description":"Open a new challenge against a right.","scopes":["challenges:write"]},{"method":"POST","path":"/v1/challenges/{challengeId}/resolve","description":"Resolve an OPEN challenge (UPHELD or OVERTURNED).","scopes":["challenges:write"]},{"method":"POST","path":"/v1/challenges/{challengeId}/withdraw","description":"Withdraw an OPEN challenge.","scopes":["challenges:write"]},{"method":"POST","path":"/v1/delivery","description":"Observe a delivery event against an ACTIVE right; constraint gate runs before the receipt is emitted.","scopes":["delivery:write"]},{"method":"POST","path":"/v1/delivery/ingest-batch","description":"Integration-adapter bridge: accepts the canonical adapter body (campaignId, siteId/deviceId, events[]) for Broadsign/VIOOH/Hivestack/PlaceExchange/Vistar/CSV feeds, resolves vendor ids to rightId + spatialAnchorId via ingest mappings, and records each event as a signed delivery. Returns per-row results.","scopes":["delivery:write"]},{"method":"GET","path":"/v1/delivery/mappings","description":"List ingest mappings (vendor campaign/placement → rightId/spatialAnchorId).","scopes":["delivery:write"]},{"method":"POST","path":"/v1/delivery/mappings","description":"Add an ingest mapping. kind=campaign binds a vendor campaign/deal/line-item id to a rightId (required to ingest); kind=placement binds a vendor site/venue/screen id to a spatialAnchorId (optional).","scopes":["delivery:write"]},{"method":"POST","path":"/v1/delivery/keys","description":"Operator mints a device-scoped delivery key for one site/player (delivery:write, restricted to the listed spatialAnchorIds). Caller must hold delivery:write and be unscoped. So a leaked per-site key can't forge plays across the estate.","scopes":["delivery:write"]},{"method":"GET","path":"/v1/events","description":"Append-only audit log.","scopes":["audit:read"]},{"method":"GET","path":"/v1/proof-packs","description":"List signed proof packs.","scopes":["proof:read"]},{"method":"GET","path":"/v1/proof-packs/{packId}","description":"Fetch a single signed proof pack.","scopes":["proof:read"]},{"method":"POST","path":"/v1/proof-packs/seal","description":"Seal a new signed proof pack covering every DELIVERY_OBSERVED event since the last seal.","scopes":["proof:read","delivery:write"]},{"method":"GET","path":"/v1/buyer/campaigns","description":"List the campaigns visible to a buyer key (distinct receipt correlationIds) with proof + attested-impression counts.","scopes":["proof:read"]},{"method":"GET","path":"/v1/buyer/proofs","description":"List the full signed proof records for a campaign (filter: campaign, cursor, limit) — each independently verifiable offline.","scopes":["proof:read"]},{"method":"GET","path":"/v1/buyer/summary","description":"Aggregated delivery for a campaign: attested impressions, total dwell, date range, and breakdowns by day and by screen.","scopes":["proof:read"]},{"method":"POST","path":"/v1/buyer/keys","description":"Operator mints a read-only, campaign-scoped buyer key for one advertiser (proof:read, restricted to the listed campaigns). Caller must hold proof:read and be unscoped.","scopes":["proof:read"]},{"method":"GET","path":"/v1/rate-cards","description":"List rate cards (the pricing-policy plane: contracted price per meter unit, targeted + currency-pinned) plus the platform default.","scopes":["settlement:read"]},{"method":"POST","path":"/v1/rate-cards","description":"Create a rate card (DRAFT by default; pass activateOnCreate to go live immediately).","scopes":["settlement:write"]},{"method":"POST","path":"/v1/rate-cards/{cardId}/activate","description":"Activate a DRAFT/SCHEDULED rate card — the explicit approve-the-pricing step.","scopes":["settlement:write"]},{"method":"GET","path":"/v1/metering","description":"Live metering summary built from every DELIVERY_OBSERVED event in the requested window. Add ?export=true for an Ed25519-signed envelope the auditor SDK can verify offline.","scopes":["settlement:read"]},{"method":"GET","path":"/v1/settlement","description":"Settlement summary projecting metering into per-party splits with floor-plus-residual allocation (sums to the exact gross). Add ?export=true for an Ed25519-signed, independently-verifiable envelope.","scopes":["settlement:read"]},{"method":"GET","path":"/v1/settlement-rules","description":"List the caller's settlement rules plus the platform default (who gets what share of each meter's gross).","scopes":["settlement:read"]},{"method":"POST","path":"/v1/settlement-rules","description":"Create a settlement rule (DRAFT by default; pass activateOnCreate to go live).","scopes":["settlement:write"]},{"method":"POST","path":"/v1/settlement-rules/{ruleId}/activate","description":"Activate a DRAFT/SCHEDULED settlement rule — the explicit approve-the-merge step.","scopes":["settlement:write"]},{"method":"GET","path":"/v1/counterparties","description":"List the tenant's identified counterparties (venues, customers, agencies, resellers, tax authorities).","scopes":["settlement:read"]},{"method":"POST","path":"/v1/counterparties","description":"Register a counterparty the settlement plane can address splits to.","scopes":["settlement:write"]},{"method":"GET","path":"/v1/disputes","description":"List delivery disputes. Filter: ?state=. Returns per-state counts.","scopes":["audit:read"]},{"method":"POST","path":"/v1/disputes","description":"Open a delivery dispute. Evidence bundle is frozen at open time.","scopes":["settlement:write"]},{"method":"GET","path":"/v1/disputes/{disputeId}","description":"Fetch a single dispute with evidence, responses, resolution and timeline.","scopes":["audit:read"]},{"method":"POST","path":"/v1/disputes/{disputeId}/transition","description":"Advance the dispute state machine (INVESTIGATING, EVIDENCE_GATHERED, OPERATOR_RESPONDED, ADVERTISER_RESPONDED).","scopes":["settlement:write"]},{"method":"POST","path":"/v1/disputes/{disputeId}/resolve","description":"Resolve the dispute. SETTLEMENT_ADJUSTMENT appends a settlement-application override in the same write.","scopes":["settlement:write"]},{"method":"POST","path":"/v1/disputes/{disputeId}/withdraw","description":"Withdraw the dispute (terminal; original opener only).","scopes":["settlement:write"]},{"method":"POST","path":"/v1/disputes/{disputeId}/escalate","description":"Escalate to mediation (non-terminal; can later resolve, withdraw, or rejoin negotiation).","scopes":["settlement:write"]},{"method":"GET","path":"/v1/compliance/export","description":"GDPR Article 15 / CCPA subject-access-request: full data export.","scopes":["audit:read"]},{"method":"POST","path":"/v1/compliance/erase","description":"GDPR Article 17 / CCPA erasure of the caller's tenant. Wildcard scope required + confirm token in body.","scopes":["*"]},{"method":"POST","path":"/v1/compliance/dsar","description":"Request a DSAR / tenant-export job (DATA_SUBJECT, TENANT_FULL, or TENANT_SLICE scope). Per-tenant cap of 5 active jobs.","scopes":["compliance:write"]},{"method":"GET","path":"/v1/compliance/dsar","description":"List DSAR jobs. Filter: ?state=REQUESTED|COLLECTING|PACKAGING|READY|DELIVERED|EXPIRED|FAILED.","scopes":["audit:read"]},{"method":"GET","path":"/v1/compliance/dsar/{jobId}","description":"Fetch one DSAR job: status, progress, timeline, and the materialised audit report.","scopes":["audit:read"]},{"method":"POST","path":"/v1/compliance/dsar/{jobId}/run","description":"Drive a REQUESTED job through the worker pipeline synchronously (collect → materialise → package → ready).","scopes":["compliance:write"]},{"method":"GET","path":"/v1/compliance/dsar/{jobId}/download","description":"Download the export artifact (content-disposition JSON). Transitions READY → DELIVERED; idempotent while DELIVERED.","scopes":["audit:read"]},{"method":"POST","path":"/v1/compliance/dsar/{jobId}/cancel","description":"Cancel a REQUESTED job before worker pickup (job lands FAILED with a manual-cancel record).","scopes":["compliance:write"]},{"method":"GET","path":"/v1/webhooks","description":"List webhook subscriptions.","scopes":["audit:read"]},{"method":"POST","path":"/v1/webhooks","description":"Create a subscription. Returns the signing secret ONCE. Wildcard scope required.","scopes":["*"]},{"method":"GET","path":"/v1/webhooks/{subscriptionId}","description":"Fetch a single subscription.","scopes":["audit:read"]},{"method":"DELETE","path":"/v1/webhooks/{subscriptionId}","description":"Permanently remove a subscription. Wildcard scope required.","scopes":["*"]},{"method":"POST","path":"/v1/webhooks/{subscriptionId}/rotate-secret","description":"Rotate the signing secret. Returns the new secret ONCE. Wildcard scope required.","scopes":["*"]},{"method":"POST","path":"/v1/webhooks/{subscriptionId}/active","description":"Pause or resume the subscription without rotating its secret.","scopes":["audit:read","delivery:write"]},{"method":"GET","path":"/v1/webhooks/{subscriptionId}/deliveries","description":"List every delivery attempt for the subscription. Filter by ?status=delivered|failed|queued|dead_lettered.","scopes":["audit:read"]},{"method":"GET","path":"/v1/webhooks/{subscriptionId}/deliveries/{deliveryId}","description":"Fetch a single delivery with full payload + response body excerpt.","scopes":["audit:read"]},{"method":"POST","path":"/v1/webhooks/{subscriptionId}/deliveries/{deliveryId}/replay","description":"Re-fire a failed delivery with the current signing secret.","scopes":["audit:read","delivery:write"]},{"method":"POST","path":"/v1/webhooks/deliveries/process-due","description":"Operator/cron hook: re-attempt the caller's due webhook retries (bounded batch). Wildcard scope required.","scopes":["*"]},{"method":"GET","path":"/v1/ai/features","description":"Discovery: full list of AI features with phase, tier, status.","scopes":["audit:read"]},{"method":"POST","path":"/v1/ai/explain-block","description":"Plain-English explanation of why a right / offer / challenge is in its current state.","scopes":["audit:read"]},{"method":"POST","path":"/v1/ai/explain-anomaly","description":"Operator-readable summary of anomalies in the recent event stream.","scopes":["audit:read"]},{"method":"POST","path":"/v1/ai/proof-pack-summary","description":"Plain-English summary of a signed proof pack's contents and verification posture.","scopes":["audit:read"]},{"method":"POST","path":"/v1/ai/policy-drafting","description":"Draft governance policy rules from a plain-English brief (operator approves before anything activates).","scopes":["audit:read"]},{"method":"POST","path":"/v1/ai/operator-copilot","description":"Natural-language queries over the tenant's rights/events/settlement state.","scopes":["audit:read"]},{"method":"POST","path":"/v1/ai/reconciliation-explanation","description":"Explain a settlement reconciliation: where the money came from, split by rule and rate card.","scopes":["audit:read"]},{"method":"POST","path":"/v1/ai/sdk-developer-assistant","description":"Integration guidance grounded in the tenant's actual SDK surface and substrates.","scopes":["audit:read"]},{"method":"POST","path":"/v1/ai/delivery-risk-prediction","description":"Deterministic delivery-risk signals over recent events, explained in plain English.","scopes":["audit:read"]},{"method":"POST","path":"/v1/ai/pilot-brief-to-policy-draft","description":"Turn a pilot brief into a draft policy + rights scaffold for operator review.","scopes":["audit:read"]},{"method":"POST","path":"/v1/ai/anomaly-morning-brief","description":"Daily operator brief: anomalies, exceptions and items needing review.","scopes":["audit:read"]},{"method":"POST","path":"/v1/ai/substrate-safety-attestations","description":"Substrate safety-attestation drafting grounded in the readiness matrix.","scopes":["audit:read"]},{"method":"POST","path":"/v1/ai/multi-language-operator-ui","description":"Operator-facing copy localisation grounded in the tenant's configured surfaces.","scopes":["audit:read"]},{"method":"POST","path":"/v1/ai/onboarding-copilot","description":"Guided onboarding answers grounded in the tenant's current setup state.","scopes":["audit:read"]},{"method":"POST","path":"/v1/ai/consent-decay-assistant","description":"Consent-expiry monitoring explained: which rights decay when, and what to renew.","scopes":["audit:read"]},{"method":"POST","path":"/v1/ai/cost-tier-fit-advisor","description":"Usage-grounded tier-fit analysis (is the tenant on the right plan).","scopes":["audit:read"]},{"method":"POST","path":"/v1/ai/demo/explain-block","description":"Public Governance Copilot demo. Runs against canned scenarios; no auth; rate-limited 3/hr per IP. Used by the /developers marketing hub.","scopes":[]},{"method":"POST","path":"/v1/ai/demo/onboarding-copilot","description":"Public demo — canned scenarios, no auth, rate-limited per IP.","scopes":[]},{"method":"POST","path":"/v1/ai/demo/proof-pack-summary","description":"Public demo — canned scenarios, no auth, rate-limited per IP.","scopes":[]},{"method":"POST","path":"/v1/ai/demo/reconciliation-explanation","description":"Public demo — canned scenarios, no auth, rate-limited per IP.","scopes":[]}]},"contractVersion":"v1.0"}