BridgeIntegration connects your Bridge account to ReconLayer so that transfer events — funding, on-chain movement, and payouts — are normalized into FlowLegs and matched against your PaymentIntents automatically.
Bridge evidence reaches ReconLayer through two of the three ingestion paths: inbound webhooks (real-time) and integration polling (catch-up / reconciliation).
Creating a Bridge integration
Display name shown in the dashboard.
Lowercase, snake_case identifier (
^[a-z0-9_]+$), unique to this integration. Used to build the inbound webhook URL and resolve organization context on incoming webhooks.Your Bridge API key, sent as
Api-Key on calls to the Bridge API (https://api.bridge.xyz/v0). Never returned by the API — responses only include hasApiKey: true.Must be
https://. ReconLayer derives the full webhook URL by appending /webhooks/bridge/{integrationKey} to this base (path normalized to avoid double slashes).At least one of:
customer, kyc_link, liquidation_address.drain, static_memo.activity, transfer, virtual_account.activity, bridge_wallet.activity, card_account, card_transaction, card_withdrawal, posted_card_account_transaction, external_account.Whether the background poll loop should include this integration.
- Builds the webhook URL:
${webhookBaseUrl}/webhooks/bridge/${integrationKey}. - Calls the Bridge API to register a webhook for the requested
eventCategories(POST /webhooksonhttps://api.bridge.xyz/v0, with anIdempotency-Keyandevent_epoch: 'webhook_creation'). - Stores the resulting
webhookId,webhookUrl, andwebhookStatuson theBridgeIntegrationDetail.
BridgeIntegrationDetail):
webhookStatus mirrors Bridge’s own status enum: disabled, active, deleted.
See Create a Bridge Integration.
Managing integrations
If you change
webhookBaseUrl while the integration’s webhookStatus is active, the request fails with 400 (“Disable the Bridge integration before changing its webhook URL.”) — disable first, update, then re-enable.Enable / disable
Receiving webhooks
Bridge sends events toPOST /webhooks/bridge/{integrationKey}. ReconLayer verifies the X-Webhook-Signature (RSA-SHA256, 10-minute replay tolerance) before running matching — see Inbound Webhooks for the full signature verification flow and error responses.
Webhook normalization
Every Bridge webhook payload becomes aRawRecord with source: 'webhook', sourceType: 'psp_report', provider: 'bridge', and integrationKey set to your integration’s key. normalizedType is taken from event_type (falling back to event_category, then 'bridge.webhook'), and normalizedId is the Bridge transfer ID (falling back to sourceRef).
From a single webhook, ReconLayer can produce up to two FlowLegs:
provider_transfer leg (phase: source)
provider_transfer leg (phase: source)
Created whenever the payload carries a Bridge transfer ID. Its
status is derived from event_object_status / the transfer’s state via this mapping:| Bridge state | FlowLeg.status |
|---|---|
funds_received, payment_processed | confirmed |
returned, refunded, canceled | reversed |
error, undeliverable, refund_failed | failed |
| anything else | pending |
FlowLegReferences captured: bridge_event_id, bridge_event_type, external_reference (from Bridge’s client_reference_id), customer_id (from on_behalf_of), destination_account_id.onchain_transfer leg (phase: transfer)
onchain_transfer leg (phase: transfer)
Created when the payload includes a
txHash, or when the source/destination payment rail is polygon or ethereum. Uses the same Bridge-state-to-status mapping above.chainId is derived from the payment rail:| Payment rail | chainId |
|---|---|
ethereum | 1 |
polygon | 137 |
FlowLegReferences captured: tx_hash, bridge_transfer_id, external_reference. Includes fromAddress, toAddress, and tokenAddress when present in the Bridge payload.Polling
In addition to (or instead of) webhooks, ReconLayer can poll Bridge for transfer state directly:The Bridge transfer ID to fetch via
GET /transfers/:id on the Bridge API.BridgeTransferPollResponse):
event_category: 'transfer', event_type: 'bridge.transfer.polled') and run through the same normalization described above, with source: 'api', signatureValid: true always, and sourceRef set to {transferId}:{updatedAt|createdAt|state}. normalizedType becomes bridge.transfer.{state} (or bridge.transfer.snapshot if no state is available).
Re-polling the same transfer is deduplicated by comparing the transfer’s updated_at/created_at/state (whichever is set first) against the value already recorded — if nothing changed, the existing record is returned as a duplicate rather than reprocessed.
See Poll a Bridge Transfer.
Background poll loop
WhenpollingEnabled: true, the Bridge poll loop (apps/api/src/bridge-poller.ts) periodically calls pollActiveBridgeIntegrations across all active, polling-enabled integrations and feeds any new/changed transfers through ingestEvidence, using actor system:bridge_poller.
| Environment variable | Default | Purpose |
|---|---|---|
BRIDGE_POLL_INTERVAL_MS | 60000 | Interval between poll cycles. Set to 0 or less to disable the poll loop entirely. |
BRIDGE_POLL_TRANSFER_LIMIT | 25 | Maximum transfers fetched per integration per cycle. |
Next steps
- Inbound Webhooks — signature verification details and the canonical evidence endpoints for providers without a native adapter.
- Ingestion Flows — how Bridge evidence flows into the matching engine.
- On-chain Integrations — for chains/networks beyond what a Bridge
onchain_transferleg captures.
