Partner Integration — API Delta Reference

Internal working reference for updating interstice-digital.gitbook.io/partner-integration.

This is not partner-facing documentation. It exists to hand engineering/docs a concrete list of what has changed between the published GitBook and the current implementation state (as of 2026-07-02), so the GitBook can be revised. Nothing on this page is a live, testable endpoint — see Base URL status. For clean, current-state source material to write the partner doc from (no diffs, no internal status), see the counterparty API reference.

Exposure model Changed

The GitBook currently documents the orchestrator REST API (services/api) as directly internet-facing, on the reasoning that it is coordination-only (holds no keys, signs no transactions). That exposure model has been superseded — deemed indefensible for a service with ~40+ endpoints, including admin/internal routes, whose isolation is enforced per-route in application code rather than by network boundary.

Before (documented today) External CP ──TLS──► Orchestrator (services/api) [directly internet-facing] After (implemented, not yet deployed) External CP ──TLS──► ALB + WAF ──► cp-gateway ──(VPC-internal, HMAC-signed)──► swap-api │ deny-by-default: only /external/cp/v1/* is routable [no public listener] │ partner-key auth · abuse-ceiling rate limit └ injects trust headers; swap-api never sees a partner credential directly

swap-api is intended to lose its public ALB listener entirely once cp-gateway is live — partners will never hold a credential that reaches it directly.

Authentication Changed

GitBook (current)
Implementation (current)
No documented key format or header scheme. Admin issues/rotates keys for institutions and counterparties through the same internal admin surface (/api/v1/admin/keys/*).
Counterparty keys are identity-linked credentials (isk_<token>), issued and resolved through the identity service — not swap-api's admin surface. Presented as a bearer token to the gateway only.
No signature/HMAC scheme documented for calls into the orchestrator itself (only a webhook-signing question is flagged as open).
The gateway resolves the partner key, then forwards to swap-api over an internal-only path with signed trust headers: entity id, participant type, an ISO-8601 timestamp, and an HMAC over timestamp.entityId.method.path with a shared secret. swap-api verifies the HMAC and a 60s replay window before trusting the identity — and never accepts these headers from a caller that isn't the gateway's own network path.
Rate-limit policy explicitly flagged as an open question.
Per-entity abuse-ceiling rate limit enforced at the gateway edge (partner tier, not consumer/metered pricing).

Base URL status Not live

Neither the GitBook nor the current implementation has a working base URL to test against right now:

Guidance for the docs rewrite: keep this section host-less. State that the base URL is assigned per-partner at onboarding once an environment is live, and give the path shape (/external/cp/v1/*) without a host, exactly as done in the table below.

Endpoint reference Changed

All paths below are relative — prefix with the base URL assigned at onboarding (see above). Every path lives under /external/cp/v1.

Discovery & profile

Method & pathNotesStatus
GET /configAssets, platform config, network configcontract frozen
GET /meCounterparty profile subsetcontract frozen
PATCH /me/supported-pairsLP-onlycontract frozen
GET /me/feeEntity-tier fee resolutioncontract frozen
GET /me/balancesCanton CC balance (locked + unlocked)contract frozen

RFQ / quoting New shape

Method & pathNotesStatus
GET /rfqsOpen RFQs this LP is eligible to quotecontract frozen
GET /rfqs/:idRFQ detail (404 if not eligible)contract frozen
POST /rfqs/:id/quoteSubmit an offered ratecontract frozen
DELETE /rfqs/:id/quote/:quoteIdWithdraw a live quotecontract frozen
GET /quotesThis LP's outstanding quotes across RFQscontract frozen

Replaces the GitBook's rfq/offerrfq/select/{offerId}rfq/finalize three-step flow. See RFQ flow shift below — this needs a rewritten walkthrough, not a find-and-replace of paths.

Swaps

Method & pathNotesStatus
GET /swapsThis entity's swapscontract frozen
GET /swaps/:idSwap detail (ownership-enforced)contract frozen
GET /swaps/:id/confirmationTrade confirmation, json or pdfcontract frozen
POST /swaps/:id/canton/prepareServer-prepared unsigned Canton tx (thin-client signing)contract frozen
POST /swaps/:id/canton/executeSubmit the signed txcontract frozen

Reports — verified on-chain transitions Expanded

Method & pathNotesStatus
POST /swaps/:id/report-hashlocknew not in GitBook's 5-transition listcontract frozen
POST /swaps/:id/report-canton-lockdocumented in GitBookcontract frozen
POST /swaps/:id/report-htlc-refreshnew not in GitBook's 5-transition listcontract frozen
POST /swaps/:id/report-eth-lockdocumented in GitBookcontract frozen
POST /swaps/:id/report-eth-claimdocumented in GitBookcontract frozen
POST /swaps/:id/report-canton-claimdocumented in GitBookcontract frozen
POST /swaps/:id/report-refunddocumented in GitBookcontract frozen
POST /swaps/by-commitment/:commitment/report-htlc-creatednew keyed by quote-commitment, not swapId — reported before a swap record existscontract frozen

Webhooks

Method & pathNotesStatus
POST /webhooksRegistercontract frozen
GET /webhooksList registrationscontract frozen
DELETE /webhooks/:idRemovecontract frozen
POST /webhooks/:id/rotate-secretRotate signing secretcontract frozen
GET /webhooks/deliveriesDelivery logcontract frozen
POST /webhooks/deliveries/:id/replayReplay a deliverycontract frozen

Retired from the external contract: the GitBook's legacy /api/v1/quotes/* routes (marked "status undecided" there) do not appear in the new surface — GET /quotes now means something different (an LP's own outstanding quotes, not the old quotes resource).

Every row above says "contract frozen," not "live." The DTOs and route surface are mounted and reachable, but each handler currently returns 501 — internal wiring to the real RFQ/swap/report services hasn't landed yet. Don't let the docs rewrite imply these are callable today.

RFQ flow shift — needs a rewritten walkthrough

This isn't a path rename — the interaction model changed shape:

GitBook flow (5 calls, linear)
Current flow (quote/withdraw against a marketplace)
POST /rfq (institution creates) → GET /rfq/availablePOST /rfq/{id}/offer (LP) → POST /rfq/{id}/select/{offerId} (institution) → POST /rfq/{id}/finalize
LP polls/subscribes to GET /rfqs, posts POST /rfqs/:id/quote (can withdraw via DELETE .../quote/:quoteId any time before acceptance). Selection/finalization happens on the institution side, outside the CP contract — see below for how that surfaces to the LP.

How an LP integrates — end to end New section

The GitBook has no equivalent walkthrough for the counterparty/LP side specifically — it describes the RFQ mechanics but not the flow an LP's own systems actually run. Quote solicitation supports two modes depending on the LP's own infra; everything downstream of a submitted quote (steps 4–6) is identical either way.

Option A — LP polls implemented
Option B — platform calls the LP not built
The LP's own systems poll (or eventually subscribe to) GET /rfqs for open RFQs it's eligible to price — filtered by its configured supported-pairs and entity tier. The LP decides, on its own schedule, which open RFQs to price.
Closer to classic RFQ/RFS semantics: the platform sends a synchronous quote request directly to an endpoint the LP registers and hosts, and the LP responds in-line with a price (or opens a stream for repeated quotes). Would require a new LP-side callback registration (analogous to the webhook secret model) and an outbound call path the platform doesn't have today — the RFQ engine has no notion of pushing to an LP, only of LPs reading and posting to it.
1
Discover or receive the request

Poll (A): GET /rfqs returns eligible open RFQs. Call (B): the platform would POST the RFQ terms to the LP's registered quote endpoint the moment a taker requests one — no LP-side discovery step at all. Only (A) exists in the current contract; (B) is a design option, not a route.

2
Call the LP's own quoting engine

Either way, the LP's market-making stack (its own internal pricing — not part of this API) computes a rate. Under (A) this happens on the LP's own schedule after it sees an open RFQ; under (B) it happens synchronously inside the LP's response to the platform's call, so the LP's quoting engine must return within whatever timeout the platform would enforce.

3
Submit the offer

Poll (A): POST /rfqs/:id/quote with the offered rate, withdrawable via DELETE /rfqs/:id/quote/:quoteId before acceptance. Call (B): the offer is the LP's synchronous response body to the platform's inbound call — there's no separate submit step, but also no withdraw window once sent.

4
Platform forwards the offer to the taker

Same for both modes from here on. The RFQ engine surfaces the relevant offer(s) to the taker (the institution) on its own side of the marketplace — privacy/anonymization rules determine what the taker sees about the quoting LP.

5
Taker accepts

Acceptance is an institution-side action (outside the CP contract) that finalizes a swap resource. Gap the LP surface doesn't currently expose a direct "your quote was accepted" read — this needs to arrive as a webhook event once the webhook surface is wired, or the LP must poll GET /swaps for a new swap referencing its accepted quote. (Under Option B, this same gap applies — a synchronous quote call doesn't imply a synchronous acceptance signal, since the taker may not accept immediately.)

6
LP continues through settlement over the same API

Once a swap exists, the LP drives its side of settlement entirely through /external/cp/v1: POST /swaps/:id/canton/prepare + /canton/execute for its Canton-side leg (thin-client signing — the LP signs a hash, the platform never holds its key), its own signer for the Ethereum-side leg, and a report-* call after each verified on-chain step (report-hashlock → lock → report-htlc-createdreport-{canton,eth}-lock → claim → report-{canton,eth}-claim, or report-refund on the failure path) until the swap reaches a terminal state.

Option A — LP polls (implemented) Taker (institution) Platform (RFQ engine) LP (counterparty) │ │ │ │──POST /rfq (internal)──►│ │ │ │◄──GET /rfqs (LP polls)─────│ │ │◄──POST /rfqs/:id/quote─────│ (LP's own pricing engine) │ │ │ │◄────best offer(s)───────│ │ │──accept (internal)─────►│ │ │ │──swap created──────────────│ (LP polls /swaps or gets webhook) Option B — platform calls the LP (considered, not built) Taker (institution) Platform (RFQ engine) LP (counterparty) │ │ │ │──POST /rfq (internal)──►│ │ │ │──POST {rfq terms}──────────►│ (synchronous, no LP polling) │ │◄──quote response────────────│ (LP's own pricing engine, in-line) │ │ │ │◄────best offer(s)───────│ │ │──accept (internal)─────►│ │ │ │──swap created──────────────│ (LP polls /swaps or gets webhook) Both options converge here — settlement is identical either way: │ each side prepares/executes its own chain leg, then reports the verified transition: │◄──report-hashlock / report-{canton,eth}-lock / report-{canton,eth}-claim / report-refund──►│ │ │ │ │◄────────────────── swap reaches terminal state ──────────────────►│
Only Option A is implemented. Option B is a documented design consideration (see the FalconX RFQ/RFS reference used to shape LP/market-maker API design) that never became a contracted route — the current /external/cp/v1 surface has no outbound-call mechanism, no LP-side callback registration, and no response-timeout handling. Treat it as a possible v2 addition, not a current option, until it has its own PR.

Security model — what changed

Known gaps Blocking real testing

Maintainer notes

Suggested handling per GitBook section: