What you can do through the API
How it works
Transactions pass through three policy stages:
Each stage evaluates its rules top to bottom, with a required catch-all default rule.
Rule configuration is not self-service. Fill out a policy template and submit it to Fireblocks Support, who apply it for you. Run policy changes through your organization’s compliance approval process before you submit them. You can read the current policy with Get TRLink policy.
A transaction’s screening status is Completed, Pending, Bypassed (approved without review, by your Trigger (Screening Policy)), or Failed.
Each destination of a multi-destination transaction is evaluated separately, and the most restrictive result applies to the whole transaction.
The order of operations depends on direction:
- Outgoing: create the TRM first, then create the Fireblocks transaction with the TRM linked.
- Incoming: create the TRM after Fireblocks detects the transaction, referencing its
txId.
Before you start
- Sumsub Travel Rule is enabled on your Sumsub account. See Sumsub’s Fireblocks integration guide.
- Fireblocks Support has enabled Sumsub on your workspace.
- Your key pair. Sumsub generates your public and private key pair, which you download from Sumsub. You sign the IVMS101 data you send with your private key, and decrypt data you receive with it.
Setup
You do this once, during onboarding.Step 1: Create a legal entity
A legal entity represents the business that is subject to the Travel Rule. It is specific to this setup, and separate from the legal entities you register in Address Registry. Most customers need one. If you operate across jurisdictions with different requirements, create one per jurisdiction and assign vault accounts to each. Only one legal entity should have no vault restriction; it is the default for every vault account not assigned elsewhere. Create it withPOST /screening/trlink/customers:
Step 2: Create the integration
Create an integration between the legal entity and Sumsub withPOST /screening/trlink/customers/integration, passing the legal entity’s customerId and Sumsub’s partnerIdent. List partners and their identifiers with GET /screening/trlink/partners.
The response returns a customerIntegrationId. Every Travel Rule call after this uses it.
Step 3: Connect to Sumsub
Share thecustomerIntegrationId with Sumsub. Sumsub supports auto-connect only: it sends your API credentials to Fireblocks directly, so you do not enter them yourself.
Step 4: Test the connection
CallPOST /screening/trlink/customers/integration/{customerIntegrationId}/test_connection. A success value of true confirms the integration can reach Sumsub.
Encrypt PII for Sumsub
Sumsub uses a nested JWT: a JWS signed with your private key, inside a JWE encrypted with Sumsub’s public key.
Fetch Sumsub’s public key before each encryption, since keys can rotate. The encrypted result goes in the TRM’s
ivms101 object:
filledFields lists, in dot notation, every IVMS101 field you populated.
To read data you receive, decrypt the JWE with your private key and verify the inner JWS with Sumsub’s public key.
Reference implementation: JWT encryption and decryption
Reference implementation: JWT encryption and decryption
Below is an example of how to encrypt and decrypt IVMS data exchanged with Sumsub. To encrypt, sign the IVMS data with your private key, then encrypt it with Sumsub’s public key. To decrypt, use your own private key to decrypt the data, then verify the signature with Sumsub’s public key. Your key pair is generated by Sumsub on their marketplace and available to download there.Here is an example of a private key:Here is an example of source IVMS data:This utility takes the paths to Sumsub’s public key, your private key, and the IVMS data, and produces an encrypted IVMS block with its filled fields:Running it (
Custom key pair upload is under consideration for future releases.
Encryption example
Sumsub’s public key response looks like this:node encrypt.js public-key.json private-key.json ivms.json) produces:Decryption example
To decrypt, use the sameTRJWTCodec class with its decryptAndDecode method. The example input below is for illustration only — it cannot be decrypted with the keys above, since it is sample data that has already expired; test with the data Sumsub actually sends you as part of creating or reading a TRM.Send an outgoing transaction
- Assess the requirement with Assess Travel Rule requirement (
POST .../trm/assess), passing the amount, asset, source, destination, andbeneficiaryVaspId. ThedecisionisREQUIRED,NOT_REQUIRED, orNEED_MORE_INFO. When it isREQUIRED,requiredFieldslists the IVMS101 fields to collect. - Encrypt the PII as described above.
- Create the TRM with
POST .../trm, using the same transaction details and theivms101object. - Create the Fireblocks transaction with
travelRuleMessageIdset to the TRM’s ownid(for exampletrm_1234567890abcdef). If the transaction already exists, link the TRM withPOST /screening/trlink/transaction/{txId}/travel_rule_message_id.
Receive an incoming transaction
- Assess the requirement, passing the Fireblocks
txIdand theoriginatorVaspId. The transaction details are filled in from thetxId. - Encrypt the PII you hold for your beneficiary.
- Create the TRM with the
txId,originatorVaspId, andivms101object. - Link the TRM to the transaction with
POST /screening/trlink/transaction/{txId}/travel_rule_message_id.
When a message needs more data
A TRM can enterPENDING when the counterparty needs more information. Fireblocks then sends a TRLink.RequiredActions notification in the Compliance webhook category, once per destination, with the trmId, customerIntegrationId, and requiredActions. See Compliance Events & Webhooks for the full payload and how to subscribe.
Read the current actions with Get required actions for a TRM, and resolve them one at a time with Resolve action for a TRM. Each call returns the updated TRM; when the last action is resolved, the TRM moves out of
PENDING.
When a transaction has no message
If a transaction that needs a TRM does not have one, it waits in the Missing Travel Rule Message state until a message arrives or your Missing Travel Rule Message Policy times out. Fireblocks sends aTRLink.NoTRMessage notification in the Compliance webhook category when this happens. See Compliance Events & Webhooks.
To decide without waiting, for example based on your own KYC data, call POST /screening/trlink/customers/integration/{customerIntegrationId}/transactions/{txId}/manual_decision with action set to ACCEPT or REJECT, and an optional reason of up to 500 characters. Do not include PII in the reason.
- The decision applies to every destination currently in the Missing Travel Rule Message state. It returns an error if there are none.
- Sending the same action again has no effect. A different action replaces the earlier one.
- Once a destination has moved past this state, its decision cannot be changed.
- Manual decisions are recorded with
source: "MANUAL".
System timeouts
Fireblocks enforces limits that you cannot configure, so a transaction never waits indefinitely: 1.5 hours for outgoing transactions, and 7 days for incoming transactions. When a transaction approaches its limit, a Wait rule is skipped instead of holding it past the limit.Multi-destination transactions
Each destination can need its own TRM. Link a TRM to a specific destination withPOST /screening/trlink/transaction/{txId}/destination/travel_rule_message_id, matching by amount and destination. The endpoint does not accept destinationScreeningId: use it from the notification only to track which destination the notification is about, or to deduplicate.
Manage messages and counterparties
All paths below start with/screening/trlink/customers/integration/{customerIntegrationId}.
TRM statuses are
PENDING, ACCEPTED, REJECTED, and FAILED. A canceled TRM cannot be reused: create a new one if the transaction goes ahead.
Testing and monitoring
Test with Testnet assets,BTC_TEST, ETH_TEST5, and XRP_TEST, before you test with real value. In the Console, Transaction History shows the policies and rules applied to each transaction, Sumsub’s responses, and the final verdict with an explanation.
To update your Sumsub credentials later, submit a ticket to Fireblocks Support.
Disconnect
Disconnect customer integration (DELETE /screening/trlink/customers/integration/{customerIntegrationId}) permanently deletes the stored credentials and the integration. Pending TRMs may fail.
Deleting a legal entity (DELETE /screening/trlink/customers/{customerId}) also deletes its integrations, TRMs, and configuration. Neither action can be undone.