Bridge — Webhooks, API Mechanics & Issuance
What this covers / who it's for. A durable, dated digest of Bridge's webhook system (event structure, signature scheme, delivery/retry/ordering, endpoint lifecycle), core API mechanics (auth, idempotency, pagination, precision, deprecation, sandbox), receipts/pricing, stablecoin issuance (mint/burn, reserves, transparency, rewards, USDB), and the recent changelog — for engineers building or reviewing anything that talks to Bridge from this repo. Facts reflect
apidocs.bridge.xyzas fetched on 2026-09-03; re-verify any claim via thebridge-developmentskill's protocol (llms.txt→ matching.mdpage, cite + date) and checkchangelog/changelog.mdbefore trusting a number here — this is a snapshot, not a live mirror. Nothing here is live traffic in Stables today:BridgeRailsProvider(D118) is registered but not granted, and thebridgewebhook source is verified/deduped/stored but has no domain handlers wired as of this fetch — see "Implications for Stables" per section for what applies once (or if) it goes live.
1. Page index
All URLs are apidocs.bridge.xyz paths, fetched 2026-09-03.
| Page | URL | Covers |
|---|---|---|
| Webhooks overview | platform/additional-information/webhooks/overview.md | Endpoint requirements, implementation flow, disabled/active/deleted, retry FAQ |
| Signature verification | platform/additional-information/webhooks/signature.md | X-Webhook-Signature header, SHA-256 over t.body, per-endpoint PEM, 10-min window |
| Event structure | platform/additional-information/webhooks/structure.md | Categories, mutations, envelope schema, JSON examples |
| Create/update/delete/list webhook endpoint | api-reference/webhooks/*.md | POST/PUT/DELETE/GET /v0/webhooks[/{id}] |
| List upcoming events / send event / view logs | api-reference/webhooks/list-upcoming-events.md, send-event.md, view-logs.md | Per-endpoint queue, manual redeliver, delivery log |
| List webhook events | api-reference/webhooks/list-webhook-events.md | GET /v0/webhook_events — account-wide replay primitive |
| Setting up webhooks (guide) | get-started/introduction/quick-start/setting-up-webhooks.md | 4-step create→verify→test→enable; sample verifiers (Python/Node/Ruby/Java/Go) |
| Authentication | api-reference/introduction/introduction.md | Api-Key header, base URLs, 401 shape |
| Idempotency | api-reference/introduction/idempotence.md | Idempotency-Key, 24h window, 422 after |
| Deprecation | api-reference/introduction/deprecation.md | Deprecated ≠ removed, changelog as the notice channel |
| Pagination | api-reference/pagination.md | Cursor pagination, starting_after/ending_before |
| Precision and rounding | platform/additional-information/precision.md | Whole-cent truncation, fee round-up, Input = Output / 0.999 |
| Pricing | platform/additional-information/pricing.md | "Contact sales@bridge.xyz" |
| Receipts | platform/additional-information/receipts.md | Bridge-sent receipts, receipt.url |
| Sandbox (simulate KYC approval) | api-reference/sandbox/simulate-kyc-approval-sandbox-only.md | Sandbox-only KYC approval simulation |
| Sandbox integration (wallets) | platform/wallets/sandbox.md | Fake addresses, simulate_deposit |
| Issuance overview | platform/issuance/overview.md | 4-step model: orchestration → minting → reserves → rewards |
| Issuance options | platform/issuance/issuance-options.md | OUSD vs Open Issuance vs USDB |
| USDB | platform/issuance/usdb.md | Bridge's closed-loop coin |
| Designing your stablecoin | platform/issuance/designing-your-stablecoin.md | Onboarding inputs, supported chains |
| Minting and burning | platform/issuance/minting-and-burning.md | No mint/burn API — automatic side effect of transfers |
| Reserve management | platform/issuance/reserve-management.md | Liquidity split, reward rates, /v0/issuance/reserves/liquidity_allocation |
| Reporting and transparency | platform/issuance/reporting-and-transparency.md | Attestations, transparency.bridge.xyz public API |
| Earning rewards | platform/issuance/rewards.md | EFFR-linked rate, payout by 5th business day, rewards history API |
| Growing your stablecoin | platform/issuance/growing-your-stablecoin.md | Stripe distribution, DEX liquidity, CEX "coming soon" |
| Changelog | changelog/changelog.md | Dated product/API updates |
2. Webhooks — envelope, categories, tolerant parsing
Envelope fields
Every delivery: api_version (v0), event_id (wh_…, globally unique — the dedup key),
event_developer_id, event_sequence (int, present in some examples, absent in others),
event_category, event_type (<category>.<mutation>), event_object_id
(= event_object.id), event_object_status (optional — populated only when the resource has a
status field, e.g. kyc_status/transfer_status; null for VA/wallet-activity events, whose
state lives in event_object.type instead), event_object (full resource, same rendering as the
GET API), event_object_changes ({field: [old, new]} diff — {} on creates, and sometimes on
updates too), event_created_at (ISO 8601). (platform/additional-information/webhooks/structure.md)
Categories and mutations
| Category | Mutations |
|---|---|
customer | created, updated, updated.status_transitioned, deleted |
kyc_link | created, updated, updated.status_transitioned |
liquidation_address.drain | created, updated, updated.status_transitioned |
static_memo.activity | created, updated |
transfer | created, updated, updated.status_transitioned |
virtual_account.activity | created, updated |
bridge_wallet.activity | created, updated |
card_account | created, updated, updated.status_transitioned |
card_transaction | created, updated, updated.status_transitioned |
posted_card_account_transaction | created |
external_acccount (sic — triple "c" on the docs page) | created, updated |
Also named in the bullet list but absent from the table: card_withdrawal. OpenAPI's
WebhookEventCategory enum additionally lists rfi (undocumented elsewhere) and spells the
account category correctly: external_account. GET /v0/webhook_events?category= also accepts
legacy values liquidation_address, virtual_account, shift4_base_deposit, indexed_deposit.
The mutation enum additionally lists canceled.
external_acccount typo vs API enum external_account. The event-type table spells the
category with three c's; OpenAPI's enum and the actual resource name are correct
(external_account). No JSON webhook example exists for this category anywhere in the docs (only
the retrieve-object schema) — verify the real field spelling against a live delivery before
hard-coding either form.
Tolerant event_type parsing
Bridge's own docs disagree on whether event_type is bare or category-prefixed: the structure
page's reference table lists bare mutations (created, updated.status_transitioned); its
JSON examples are mixed — some transfer examples are bare ("created"), one is prefixed
("transfer.updated"), while customer/kyc_link/virtual_account.activity examples are
consistently prefixed; the OpenAPI schema asserts values "will be prefixed with the
event_category" — the canonical claim, contradicted by the table and some examples.
Implication: parse tolerantly — prefix with event_category only when event_type doesn't
already start with it (never double-prefix); never string-compare the raw field. See §5.
3. Signature scheme
Header: X-Webhook-Signature: t=<unix_ms>,v0=<base64 signature>. Verification: parse t/v0;
build message "<t>.<raw body>" (raw request body bytes, no pre-JSON-decode); SHA-256 digest;
strict-base64-decode v0; verify against the endpoint's public_key (per-endpoint PEM). The
algorithm is not named on the signature page; the setup guide's sample code uses RSA PKCS#1
v1.5 with SHA-256. Replay tolerance: reject events older than "a few minutes, e.g. 10 minutes"
and — per Bridge's own guidance — return 400 to request a retry. Key rotation is not
documented. (platform/additional-information/webhooks/signature.md,
get-started/introduction/quick-start/setting-up-webhooks.md)
Documented cross-language disagreement in Bridge's own sample verifiers. The setup guide's
five sample verifiers disagree on the hashing step: Go explicitly double-hashes —
sha256(sha256("t.body")) — then rsa.VerifyPKCS1v15(pub, crypto.SHA256, hashed); Python /
Node / Java feed the single SHA-256 digest of "t.body" into a SHA256-with-RSA verify call,
which itself hashes internally — an effective double hash, consistent with Go; Ruby
verifies the un-digested raw payload directly against a SHA256-with-RSA verifier — a
single hash, inconsistent with the other four. Stated plainly rather than resolved:
BridgeSignatureValidator must be verified against a real production Bridge event before
go-live — sandbox endpoints receive zero events (§4), so this cannot be tested pre-prod.
PHP's openssl_verify() hashes internally given a digest algorithm — called here on the
un-digested raw "<t>.<rawBody>" string, exactly as Ruby's sample verifier does — so this
app's implementation (BridgeSignatureValidator, app-modules/webhooks/README.md:227-245)
follows the single-hash net effect (Ruby, not Python/Node/Java/Go). Concretely: our
implementation matches only 1 of Bridge's 5 sample conventions, which RAISES the go-live
verification risk stated above — it must be verified against a real production delivery before
go-live, not assumed correct by majority convention; unconfirmed against a live delivery.
Stale timestamp: Bridge suggests 400, this app returns 401. This app's bootstrap/app.php
render callback maps every false SignatureValidator return (Bridge included) to HTTP 401
uniformly, for consistency with every other source — a deliberate, documented deviation, safe
because Bridge retries any non-2xx response regardless of status code.
4. Delivery, retry, ordering, endpoint lifecycle, replay
Delivery: POST, application/json; endpoint should "return a 200 status … as quickly as
possible to avoid timeouts and retries" — no specific timeout value documented.
Retry: "up to two days" of automatic exponential backoff on an unavailable endpoint; exact schedule/intervals not stated. Each retry carries a fresh timestamp in the signature header (not a byte-identical resend).
No ordering guarantee. Nothing promises in-order delivery. The only sequencing primitives are
event_sequence (int, present in some envelope examples, absent in others) and
GET /v0/webhook_events, stated to return results "ordered by their event_sequence in
ascending order" — a pull-API guarantee, not a push-delivery one.
GET /v0/webhook_events as the replay primitive. Account-wide (not per-endpoint), last
90 days, ascending event_sequence, limit up to 500 (vs 100 elsewhere), filterable by
category. Combined with per-endpoint GET /v0/webhooks/{id}/events (next 10 queued) and
POST /v0/webhooks/{id}/send {event_id} (manual redeliver, "does not guarantee immediate
delivery"), this is the recovery path after an outage past the two-day retry horizon, or after
re-enabling an endpoint.
No backlog replay on re-enable, since 06/29/2026. Re-enabling a disabled endpoint no longer
replays the backlog queued while disabled (changelog). Recovery is manual: list events via
GET /v0/webhook_events filtered to the outage window, then send each one.
Endpoint lifecycle. Webhook: id (wep_…), url, status
(active|disabled|deleted), public_key (per-endpoint PEM), event_categories[]. Created
via POST /v0/webhooks (Idempotency-Key required): url HTTPS + valid X.509 ("doesn't need to
be live, but the host must be reachable"); event_epoch = webhook_creation (a few events
preceding creation, "for convenience") or beginning_of_time; starts disabled. Max 5
endpoints (active + disabled combined, per developer account). Updated via
PUT /v0/webhooks/{id} — url, status, event_categories (new categories deliver only from
that point onward). A URL change requires disabling the endpoint first. Deleted via
DELETE → status: deleted, no longer accessible.
5. JSON samples (verbatim, ≤40 lines each)
customer — customer.created (fires at KYC-link creation, before any user action —
status: not_started; client_reference_id: null here, populated later once we set it):
{
"api_version": "v0", "event_id": "wh_2tEL5NVw3dkEpLRJz4dS8gqWYX1", "event_sequence": 1,
"event_category": "customer", "event_type": "customer.created",
"event_object_id": "c_2tEKzQmNvR9xJfPdL8mY4hsBk3A", "event_object_status": "not_started",
"event_object": {
"id": "c_2tEKzQmNvR9xJfPdL8mY4hsBk3A", "first_name": "Jane", "last_name": "Doe",
"email": "jane.doe@example.com", "type": "individual", "status": "not_started",
"has_accepted_terms_of_service": false, "client_reference_id": null,
"tos_link": "https://dashboard.bridge.xyz/tos/c_2tEKzQmNvR9xJfPdL8mY4hsBk3A",
"rejection_reasons": [],
"endorsements": [{"name": "base", "status": "incomplete", "requirements": {"complete": [],
"pending": [], "missing": {"id_verification": "Identity verification required"}, "issues": []}}],
"created_at": "2025-11-19T21:14:58.328Z", "updated_at": "2025-11-19T21:14:58.328Z"
},
"event_object_changes": {}, "event_created_at": "2025-11-19T21:14:58.328Z"
}
kyc_link — kyc_link.updated.status_transitioned (customer_id: null even mid-transition —
exact moment it populates, and whether it appears in event_object_changes, is undocumented):
{
"api_version": "v0", "event_id": "wh_tmyqyd9q5nsVJazfux9EiQC", "event_category": "kyc_link",
"event_type": "kyc_link.updated.status_transitioned",
"event_object_id": "3694522e-6bed-4660-a803-f599b50c7691", "event_object_status": "incomplete",
"event_object": {
"id": "3694522e-6bed-4660-a803-f599b50c7691", "type": "individual",
"email": "danyka+wintheiser@quigley.xyz", "kyc_link": "<KYC link>", "tos_link": "<ToS link>",
"full_name": "Danyka Wintheiser", "kyc_status": "incomplete", "tos_status": "approved",
"customer_id": null, "persona_inquiry_type": "gov_id_db"
},
"event_object_changes": {"kyc_status": ["not_started", "incomplete"],
"tos_status": ["pending", "approved"]},
"event_created_at": "2024-02-09T17:00:43.709Z"
}
transfer — created, status awaiting_funds (bare event_type — one of the pages' own
inconsistent examples, see §2):
{
"api_version": "v0", "event_id": "wh_123abc456def", "event_category": "transfer",
"event_type": "created", "event_object_id": "tr_abc123xyz789",
"event_object_status": "awaiting_funds",
"event_object": {
"id": "tr_abc123xyz789", "state": "awaiting_funds", "amount": "1500.00", "currency": "usd",
"developer_fee": "0.0", "client_reference_id": null, "on_behalf_of": "cust_alice",
"source": {"currency": "usdc",
"from_address": "0x1111111111111111111111111111111111111111", "payment_rail": "polygon"},
"destination": {"currency": "usd", "payment_rail": "ach",
"external_account_id": "external-account-123"},
"receipt": {"gas_fee": "0.0", "exchange_fee": "0.0", "developer_fee": "0.0",
"initial_amount": "1500.00", "subtotal_amount": "1500.00", "final_amount": "1500.00"},
"created_at": "2025-07-22T11:26:55.000Z", "updated_at": "2025-07-22T11:26:56.000Z"
},
"event_object_changes": {}, "event_created_at": "2025-07-22T11:26:00.000Z"
}
Implications for Stables
The bridge webhook source (D118) is verified/deduped/stored today with no domain handlers
wired — see app-modules/webhooks/README.md
for what's actually built. Intended domain handlers (event type → module → command) are designed,
not shipped, in the alignment design
§3 — tenant resolution bootstraps by setting client_reference_id on every outbound
kyc_links/customers/VA/transfer create call; provider_customers covers events carrying only
customer_id. Go-live sequencing is recorded in D118
§Go-live and design §6/§7.
6. API mechanics
Authentication. Api-Key header on every request (the intro page calls this "HTTP Basic
Auth" but the shown example is a bare header, not RFC 7617 Basic auth — wording inconsistency,
not a different mechanism). HTTPS only. Missing/invalid key → 401
{code: required|invalid, location: "header", name: "Api-Key", message}. Sandbox keys are scoped
per developer account, invisible to teammates. Scoped API keys (changelog 03/23/2026) add
resource-level permissions, immutable after creation. Base URLs: https://api.bridge.xyz/v0
(prod), https://api.sandbox.bridge.xyz (sandbox) — the idempotency page's own example uses
/v1/customers, the only v1 reference seen anywhere; treat as a docs typo, not a second version.
(api-reference/introduction/introduction.md)
Idempotency. Idempotency-Key required on every POST; must NOT be sent on
GET/PUT/PATCH/DELETE. 24h window: same key returns the original response. Retry must use the
identical body — any changed/added/removed field (incl. nested, e.g. transfer initiation
data) is a conflicting reuse, not a silent update. Reuse after 24h → 422. Bridge recommends a
persisted UUID per logical request. (api-reference/introduction/idempotence.md)
Pagination. Cursor-based on item id, default newest→oldest. limit 1–100.
starting_after=<last id> walks older; ending_before=<first id> walks newer; never both.
{data: [...], count?}; stop when data is empty. Exception: GET /v0/webhook_events is
ascending by event_sequence, limit up to 500 (§4). (api-reference/pagination.md)
Precision and rounding. Amounts truncate to whole USD cents even for 6-dp stablecoins —
fractional cents "ignored, not processed or refunded." Rounding favors "at least the minimum
amount of fees owed to all parties" — developer fee rounds up. Worked example: off-ramp
$100,100.119999 USDT at 10 bps dev fee → truncate $100,100.11 → fee $100.10011 → round up
$100.11 → customer receives $100,000.00. Clean fixed-output formula:
Input = Output / 0.999, round up to the nearest cent (bakes in a ~10 bps "standard Bridge
exchange fee"). Silent on non-USD fiat precision and crypto-to-crypto rounding.
(platform/additional-information/precision.md)
Deprecation and versioning. "Deprecated" ≠ removed — migration guidance is inline on the
deprecated surface, "sufficient advance notice before removing," no fixed sunset period
stated; the changelog is the only announcement channel. Every webhook envelope carries
api_version: "v0"; OpenAPI info.version is '1'; no header-based versioning documented.
(api-reference/introduction/deprecation.md)
Sandbox behaviour. Base https://api.sandbox.bridge.xyz, per-developer keys. Webhook
endpoints can be created in sandbox, but sandbox sends zero webhook events — real webhook
testing needs production keys and a live endpoint (the load-bearing fact behind the
signature-scheme caveat in §3). POST /v0/customers/{id}/simulate_kyc_approval (sandbox-only)
sets KYC approved, fills required data from existing/sandbox defaults, approves pending
endorsements. Bridge Wallets: creation returns a fake address bypassing the external provider;
POST …/wallets/{id}/simulate_deposit {amount, currency} runs the full deposit pipeline to a
terminal state. Silent on: transfer/VA simulation, data reset, rate limits.
(api-reference/sandbox/simulate-kyc-approval-sandbox-only.md, platform/wallets/sandbox.md)
Implications for Stables
Idempotency-Key derivation must be stable per logical operation, never embed a mutable field —
bridge-sdk's HasIdempotencyKey trait (bridge-development skill) is the in-repo mechanism.
Pagination cursors map onto this repo's mirror backfill/poll conventions
(app-modules/rails/README.md). Precision: Bridge
amounts must be stored as decimal strings (never floats — the SDK already enforces this) and
reconciliation must expect final_amount ≤ initial_amount − fees with cent truncation, never
bit-for-bit against 6-dp on-chain amounts. Because sandbox sends zero webhook events, no Bridge
webhook path here can be end-to-end tested against a real delivery pre-production —
BridgeSignatureValidatorTest/BridgeTenantResolverTest are necessarily synthetic; production
go-live carries first-real-event verification risk (§3).
7. Receipts and pricing
Receipts. "Bridge is required to send receipts for transactions processed through our
system" — content: amount, fees, Bridge's legal disclosures; branding customised during
integration. Transfer payloads carry a receipt object (gas_fee, exchange_fee,
developer_fee, initial_amount, subtotal_amount, final_amount, optionally
destination_tx_hash and url — https://dashboard.bridge.xyz/transaction/{id}/receipt/{id}).
Silent on delivery channel, who sends it, opt-out, localisation.
(platform/additional-information/receipts.md)
Pricing. The entire page: "Please reach out to sales@bridge.xyz to discuss pricing." No
rates/tiers/fee schedule published. Adjacent facts: FedNow offramp beta is $0.50/transfer
existing devs, $1.00 new (changelog 08/17/2026); developer fees are separately configurable via
the Developers API tag (not fetched); precision's Input = Output / 0.999 implies a ~10 bps
"standard Bridge exchange fee" but is not an explicit price statement.
(platform/additional-information/pricing.md)
Implications for Stables
Surface Bridge's receipt.url in transaction detail rather than re-rendering its legal
disclosure content (see BridgeTransferUpdatedHandler, §2). Pricing has no programmatic source —
any fee assumption in rate quoting must come from the Developers fee-configuration API or a
commercial agreement, never scraped from public docs.
8. Stablecoin issuance and rewards
No mint/burn API. "As issuer, Bridge handles all minting and burning for you" — no documented
endpoint; both are automatic side effects of the orchestration/transfer pipeline. Mint: incoming
fiat deposit → allocate to reserve accounts → mint on-chain → deliver to user's wallet. Burn:
incoming on-chain stablecoin → burn → release fiat from reserves → send to bank or crypto
address. Backing: "at least 1:1 by equivalent fiat value in reserves." Redemption timing isn't
stated here (see reserve-management). (platform/issuance/minting-and-burning.md)
Liquidity allocation endpoint. POST /v0/issuance/reserves/liquidity_allocation
(Idempotency-Key), body {allocation_percent, allocation_minimum} →
{previous_*, new_*}; GET same path returns {allocation_percent, allocation_minimum}. Goal:
reserves ≥100% collateralised; developer controls on-demand-liquid vs treasuries split, and
within liquid, USD vs on-chain-stablecoin — each side has a percentage + a minimum; "if both
on-demand balances are below their respective minimums, reserve allocations will be rebalanced
accordingly." Silent on which stablecoin the endpoint targets (no ticker param) — an
account-level knob, not per-coin as documented. (platform/issuance/reserve-management.md)
Reward/redemption table: treasuries ≈ EFFR − 20 bps, US banking hours (tokenized treasuries partly redeemable outside hours, "within 1 business day"); off-chain USD ≈ EFFR − 200 bps, US banking hours; on-chain stablecoins 0%, 24/7. $100m AUM examples: redemption-first 50/50 → ~2.2% effective; reward-first 10/90 → ~3.3% effective.
Transparency endpoint (public, no key, different host):
GET https://transparency.bridge.xyz/v0/stablecoins/{stablecoin} → last_updated,
total_onchain_amount, total_reserve_amount, reserves[]{type: cash|treasury, amount},
collateralization_ratio (6-dp strings). usdb is queryable today.
(platform/issuance/reporting-and-transparency.md)
USDB. Bridge's off-the-shelf closed-loop coin — "only usable within Bridge wallets and
payment rails," not transferable to third parties or traded publicly; still supported
indefinitely. OUSD (run by the independent Open Standard consortium) is Bridge's suggested
open-loop alternative. USDB appears in transfers as currency: "usdb",
payment_rail: "bridge_wallet". (platform/issuance/usdb.md, issuance-options.md)
Rewards. Accrue "continuously" on treasury allocation; cash reserves "generally don't
generate rewards." Revenue-share wording is inconsistent even within one page — "all revenue
(minus issuance fees)" vs "the majority." Payout by the 5th business day of the following
month, as minted tokens to a specified wallet or fiat to a bank — developer's choice. Rewards
history API (GET /v0/rewards/{currency}/history, changelog 06/22/2026): daily records, t-2
business-day lag, ≤90 days/page, cursor-paginated. "Coming soon" per the pages: self-service
on-demand claim, automated per-user reward splitting. (platform/issuance/rewards.md)
Implications for Stables
No issuance work exists in this repo today — BridgeRailsProvider (D118) implements 11 of 17
capability interfaces over Onboarding/FiatRails/Conversion/Custody, not issuance; see
provider-landscape §"Bridge's registered capability groups." If a
future increment adds issuance: model mint/burn as ordinary transfer.* webhook events, not a
separate call; the reserve-allocation endpoint is a single account-level knob suited to a
treasury-ops maker/checker surface, not per-tenant; any user-facing yield display must be built
on the t-2-lagged history API, never a live number.
9. Changelog — most recent ~20 entries
| Date | Entry |
|---|---|
| 08/17/2026 | FedNow offramps beta (24/7 instant USD out); waitlist; $0.50/transfer existing devs, $1.00 new |
| 07/28/2026 | USDT on Tempo (usdt.tempo) and USDC on XDC (usdc.xdc) added to Orchestration APIs |
| 06/22/2026 | Webhook reactivation no longer replays backlog (effective 06/29); replay via list-upcoming + send |
| 06/02/2026 | Same reactivation notice (duplicate entry with links, as published) |
| 06/22/2026 | Issuance Rewards History API GET /v0/rewards/{currency}/history — daily, t-2 lag, ≤90 days/page |
| 06/23/2026 | Prefunded wallets emit bridge_wallet.activity; fiat legs may still emit virtual_account.activity/static_memo.activity |
| 06/02/2026 | Bridge Wallet history gains starting_time/ending_time (ISO 8601), combinable with id cursors |
| 05/28/2026 | Liquidation Address return_instructions{address, memo?} replaces deprecated return_address |
| 05/04/2026 | FedNow onramps live, auto-enabled; inspect payment_received_rail (Transfer) / payment_rail (VA) |
| 05/04/2026 | Bridge Wallet activity webhooks + GET /v0/customers/{id}/wallets/{id}/history |
| 04/27/2026 | POST /v0/customers/{id}/external_accounts/{id}/deactivate (soft-disable); DELETE re-documented |
| 04/27/2026 | USDC and usDCBL on Aptos across orchestration |
| 04/22/2026 | Transfers gain payment_received_rail (may differ from requested payment_rail) |
| 04/20/2026 | USDC on Sui |
| 04/20/2026 | Stellar memoless_to_address (muxed) deposits; memo flow retained |
| 04/03/2026 | USDC on HyperEVM |
| 04/01/2026 | [Beta] fixed fees + per-rail fees + min/max bounds for Virtual Account onramps (gated) |
| 03/27/2026 | Tempo Mainnet across all products |
| 03/27/2026 | New payment states refund_in_flight, refund_failed in Transfers/VAs/Liquidation Addresses + webhooks |
| 03/27/2026 | Effective 05/01/2026: client_reference_id added to v0/customers + customer webhooks; rejection_reasons strings may change — treat as free-form |
| 03/24/2026 | Prefunded Accounts API deprecated (still supported indefinitely; improvements go to Bridge Wallets) |
| 03/23/2026 | Scoped (immutable, resource-level) API keys |
| 03/23/2026 | GBP FPS on/offramps GA; requires faster_payments endorsement |
Older entries (03/09/2026 → 07/15/2025, per the changelog page): USDT on Solana; USDT↔MXN/BRL via
SPEI/Pix on Ethereum/Plasma/Tron; Tron USDT custodial wallets; External Account webhooks
(03/09/2026, with deactivation_reason/deactivation_details); USDC.Celo ramps; per-transfer
return_instructions for crypto returns; Fixed Outputs; EURC on Ethereum; USDT on Plasma; GBP FPS
beta; USDG on Solana; BRL Pix; reverse exchange rates; missing_return_policy state; proof of
address via documents[].purpose = proof_of_address. Dates on the changelog page are not
strictly monotonic — the 06/22 and 06/02 duplicate-dated reactivation entries above are exactly
as published.
10. Bridge doc inconsistencies / gaps
- Signature hash count: Go/Python/Node/Java samples effectively double-hash; Ruby single-hashes. Never resolved on the signature page (§3).
- Stale-webhook response code: signature page says 400; this app deliberately returns 401 for consistency with every other source (§3) — a documented app-side deviation, not a docs bug.
event_typeprefixing: category table shows bare mutations, examples mix bare/prefixed, the OpenAPI schema asserts prefixed-is-canonical (§2).external_acccountvsexternal_account: table has a typo (triple c); OpenAPI enum is correct; no JSON example exists for this category at all.event_object_status: null for VA/wallet-activity events (state lives inevent_object.typeinstead), populated for customer/kyc_link/transfer — an undocumented shape inconsistency.- "HTTP Basic Auth" wording: auth page calls the
Api-Keyheader "HTTP Basic Auth," but the example is a bare custom header, not RFC 7617 Basic auth. /v1/customersin the idempotency example: the onlyv1reference anywhere; every other page uses/v0— likely stale, unconfirmed.- Revenue-share wording: issuance overview says "all revenue (minus issuance fees)" in one paragraph, "the majority" in another, same page.
kyc_link.customer_idpopulation timing: undocumented whether/when it surfaces inevent_object_changes— every sampled example still showsnull.- Delivery timeout / retry backoff: "as quickly as possible" and "exponential, up to two days" are the only guidance; no numeric timeout or schedule published.
- Key rotation mechanics: undocumented for webhook signing keys (this app's
BridgeSignatureValidatorsupports comma-separated multi-key rotation defensively, not because Bridge describes a rotation flow).
11. Open questions for Bridge
Consolidated + tracked in flow-alignment.md §Open questions; this section keeps this page's own detail.
- Which hashing convention is correct for signature verification — single (Ruby) or double (Go/Python/Node/Java)? Unresolvable from docs; needs a real production delivery (sandbox sends zero events).
- What is the actual delivery timeout, and the exact retry backoff schedule (intervals, jitter, cap) within the two-day window?
- When exactly does
kyc_link.customer_idpopulate, and does it surface inevent_object_changes? - Is
/v1/customers(idempotency guide) a live second API version, or a stale/v0typo? - Does
/v0/issuance/reserves/liquidity_allocationtarget one stablecoin per account, or is there an undocumented per-coin parameter for multi-coin issuers? - What triggers webhook signing-key rotation on Bridge's side — is there a notification, or is our comma-separated multi-key support purely defensive?
12. Fetched 2026-09-03
All paths relative to https://apidocs.bridge.xyz/, fetched 2026-09-03, HTTP 200 on first try.
- Webhooks:
platform/additional-information/webhooks/{overview,signature,structure}.md·api-reference/webhooks/{create-a-webhook-endpoint,update-a-webhook,delete-a-webhook, get-all-webhook-endpoints,list-upcoming-events,list-webhook-events,send-event,view-logs}.md·get-started/introduction/quick-start/setting-up-webhooks.md - API mechanics:
api-reference/introduction/{introduction,idempotence,deprecation, postman}.md·api-reference/pagination.md - Receipts/pricing/precision:
platform/additional-information/{precision,pricing,receipts, faq}.md - Sandbox:
api-reference/sandbox/simulate-kyc-approval-sandbox-only.md·platform/wallets/sandbox.md - Issuance:
platform/issuance/{overview,issuance-options,usdb,designing-your-stablecoin, orchestration,minting-and-burning,reserve-management,reporting-and-transparency,rewards, growing-your-stablecoin,faq}.md - Changelog:
changelog/changelog.md - JSON-sample support (§5, via BRIEF-2):
api-reference/kyc-links/{generate-the-links-needs-to-complete-kyc-for-an-individual-or-business, check-the-status-of-a-kyc-link}.md·platform/customers/customers/kyclinks.md·api-reference/external-accounts/retrieve-an-external-account-object.md·api-reference/bridge-wallets/get-transaction-history-for-a-bridge-wallet.md