Global Travel Rule
Global Travel Rule (GTR) is one of Covalent's Travel Rule providers: a network of VASPs that verify addresses and exchange encrypted IVMS101 data through GTR's API.
The GTR integration has not yet been tested against GTR's UAT or production environment. See Known Limitations.
Provider Config
Section titled “Provider Config”| Field | Value |
|---|---|
| Name | gtr |
| Display name | Global Travel Rule |
| Protocol | gtr |
| Active | true |
| Discovery | Address verification against GTR allowlisted VASPs |
| Transport | mTLS REST API with Curve25519 encrypted IVMS101 |
| GTR environment | test: UAT, uat-platform.globaltravelrule.com; live: production, platform.globaltravelrule.com |
Required Provider Fields
Section titled “Required Provider Fields”Save GTR's credentials for each environment with PUT /api/v2/providers/gtr, or in the dashboard under Travel Rule, Providers, and enable GTR with a live key (PATCH /api/v2/providers/gtr). See Providers and Integrations. Every field is required.
| Field | Type | Value |
|---|---|---|
vaspCode |
text |
Your GTR VASP code: 4 to 64 letters, digits, _, = or -. |
accessKey |
password |
Your GTR API access key. |
secretKey |
password |
Your GTR API secret key. It never leaves the App Worker: each GTR call carries an X-Authorization token made from it. |
certificate |
textarea |
The TLS client certificate GTR issued you, in PEM (-----BEGIN CERTIFICATE-----). |
tlsPrivateKey |
password |
The certificate's private key, in PEM. |
publicKey |
text |
Your VASP's Ed25519 public key for PII encryption, 32 bytes in standard Base64. |
privateKey |
password |
The matching Ed25519 seed (32 bytes) or secret key (64 bytes), in standard Base64. It must produce publicKey. |
callbackProxySecret |
password |
At least 32 characters. Your callback proxy adds it to every GTR callback: see Callbacks. |
The password fields hold secrets. Covalent stores all of the credentials encrypted. An API answer says which fields hold a value, never the value; the dashboard shows only the saved vaspCode, certificate and publicKey. Saving checks only that every field holds a value: the connection test checks the values.
Covalent sends your company profile to GTR as your VASP's identity: the originating VASP of an outgoing transfer, the beneficiary VASP of an incoming one. Complete it in the dashboard under Settings, Company: registered name, country of registration, registered address, city and address country, plus an LEI, or a registration number and registration authority code. One profile serves test and live.
Capabilities
Section titled “Capabilities”| Capability | Value |
|---|---|
| Beneficiary address | Required |
| Originator address | Optional |
| Beneficiary IVMS101 | Required: beneficiary.beneficiaryPersons, one natural person, or a legal person followed by its natural-person representatives |
| Originator IVMS101 | The originator customer's verified Travel Rule identity, not the request's originator |
| Beneficiary VASP | Not required upfront: GTR's address search finds it |
| Destination memo | Supported, sent as GTR's tag |
| Wallet proof type | None |
| Intermediary VASPs | Not supported: IVMS101 data with a transfer path or a broker VASP is refused |
GTR carries these networks and assets. Network names are matched without case, and aliases such as eth, matic and bnb are accepted. The asset symbol must match exactly.
| Network | GTR code | Assets |
|---|---|---|
ethereum |
ETH |
ETH, MATIC, LINK, UNI, SHIB, USDT, USDC, DAI, BUSD, TUSD, USDP, FRAX, LUSD, GUSD, PYUSD |
arbitrum |
ARBITRUM |
ETH, ARB, USDT, USDC, DAI |
optimism |
OP |
ETH, OP, USDT, USDC, DAI |
base |
BASE |
ETH, USDC |
polygon |
MATIC |
MATIC, USDT, USDC, DAI |
bsc |
BSC |
BNB, BUSD |
avalanche |
AVAXC |
AVAX, USDT, USDC |
solana |
SOL |
SOL, USDT, USDC, PYUSD |
tron |
TRON |
TRX, USDT, TUSD |
stellar |
XLM |
XLM, USDC |
bitcoin, bitcoin-cash, litecoin, dogecoin, ripple, cardano, polkadot, cosmos, algorand, near, fantom |
The coin's symbol | Each network's own coin: BTC, BCH, LTC, DOGE, XRP, ADA, DOT, ATOM, ALGO, NEAR, FTM |
Forwarder
Section titled “Forwarder”Cloudflare Workers cannot present a TLS client certificate taken from stored data. Covalent therefore sends every GTR call through a forwarder: a small service in a container, one for your company in each GTR environment.
- Each call carries your saved
certificateandtlsPrivateKeyto the forwarder, which makes the mutual TLS request. It keeps them in memory only and writes nothing to disk. Its logs hold each call's method, path, status, timing and error code. - It reaches only GTR's API host for the environment, never a host named by the request. It verifies GTR's server certificate, passes on only
Content-TypeandX-Authorization, follows no redirects, and waits at most 15 seconds for GTR. - Requests and answers are limited to 512 KiB. A forwarder takes 16 calls at once, and answers
BUSYabove that. - It sleeps after 10 idle minutes; the next call waits for it to start. One that does not start within 15 seconds fails the call with
FORWARDER_UNAVAILABLE, and the next call starts it again. - Covalent does not retry GTR calls automatically, and never resends a verification, decision or transaction report whose answer was lost.
- The forwarder only makes Covalent's calls to GTR. It does not receive GTR's callbacks.
Callbacks
Section titled “Callbacks”GTR calls your company's host on one path for each environment:
POST /api/system/trp/gtr/<environment>/<providerId>The path is listed in the provider's callbackPaths once it has been saved. Register it with GTR. The path's environment chooses that environment's credentials. A provider ID that is not your enabled GTR provider, with credentials for that environment, answers 503 { "error": "Provider unavailable" }.
Covalent does not check GTR's TLS client certificate itself. The App Worker accepts a GTR callback only when it carries both of these headers, and answers 401 { "error": "Unauthenticated callback" } otherwise:
| Header | Value |
|---|---|
x-gtr-client-verified |
SUCCESS |
x-gtr-proxy-secret |
The environment's callbackProxySecret |
These headers must come from a reverse proxy that you run in front of the callback path. It must verify GTR's TLS client certificate (mutual TLS), add both headers only to calls that pass, and forward them to your company's host. Covalent does not provide or run this proxy; without it, every GTR callback is refused.
A verified callback answers 200 in GTR's format: verifyStatus, verifyMessage, and data where there is some. A body that is not JSON answers 400, one over 512 KiB 413, and a callback Covalent cannot process 503, with verifyStatus 100008 and the error code, or Callback processing failed, as verifyMessage.
callbackType |
From GTR | Covalent's answer |
|---|---|---|
0 |
Health check | Success, with no data. |
10 |
Which VASP holds an address | Yours, when exactly one verified wallet in the environment has the address (and tag) on that network; otherwise pending (100002). |
6 |
Address verification | Success when exactly one verified wallet has the address and its customer has a verified Travel Rule identity; otherwise 200001. |
13 |
A pending address check's result | Success. Covalent's address search reads results from GTR itself. |
4, verificationDirection 2 |
PII verification of an incoming transfer | See Incoming Transfers. |
4, verificationDirection 1 |
The beneficiary VASP of your transfer asks for the originator's data | Released only for a completed outgoing GTR transfer to that VASP with the same transaction ID, amount, address and tag, when the persons it names match your customer's verified identity. |
9 |
Whether a transaction ID belongs to your transfer | Success only for a completed outgoing GTR transfer to that VASP with that transaction ID, asset, network, address and tag; otherwise 200007. |
7 |
An incoming transfer's transaction ID | Stored. The transfer completes once GTR's status confirms it. |
15 |
The PII verification result of your outgoing request | Stored, then applied: see Outgoing Transfers. A second result that differs from a verified one holds the transfer for review. |
17 |
The end of a request | Success. Covalent reads the outcome from GTR's status. |
| Any other | 100004. |
After a 4, 7, 15 or 17 callback about a request it knows, Covalent reads the request's status from GTR (GET /api/verify/query) and updates the transfer.
Outgoing Transfers
Section titled “Outgoing Transfers”Callers do not call GTR directly: they create transfers with POST /api/v2/transfers (see Transfers). GTR can carry a transfer when the request has a valid beneficiary (see Capabilities), the originator customer has a verified Travel Rule identity, your company profile is complete, and the asset and network are in the table above.
"preferredProtocol": "gtr" is refused with 400 VALIDATION_ERROR unless GTR is enabled, has credentials for the key's environment, and the request has a beneficiary with at least one person. Covalent then tries GTR first, unless the beneficiary VASP was last reached through another provider. Another enabled provider may still carry the transfer: when GTR's address search finds no VASP, or when GTR's attempt fails before Covalent reserves a GTR request, as for an originator without a verified identity or an incomplete company profile. GTR's attempt is under cascade.attempts: vasp_not_found, or error with the reason, such as GTR: VERIFIED_IDENTITY_REQUIRED. Once a GTR request is reserved, no other provider carries the transfer.
- Covalent screens the transfer, then runs VASP discovery.
- It reads the beneficiary VASP's record, with its PII public key, from GTR's directory.
- It builds the IVMS101 message: your customer's verified identity as originator, with
originatorAddresswhen given; the request'sbeneficiary, with the beneficiary address and memo; your company profile as originating VASP. - It reserves a request ID,
cv-and a UUID, before it sends anything. A sent request's attempt carries it asexternalId. - It sends one verification request (
POST /api/verify/v2/one_step): the amount, its value in USD at Covalent's FX rate, the asset, GTR's network code, the memo astag, and the IVMS101 message encrypted for the beneficiary VASP's key, with a salted SHA-512 manifest of its fields.
| GTR's answer | Transfer |
|---|---|
| Verified, with the beneficiary VASP's IVMS101 | status.theirs is accepted. Covalent screens the beneficiary data, and each additional person in it: approved moves the transfer to awaiting_counterparty; a review holds it (held, compliance pending); a rejection ends the GTR request first, then the transfer is rejected. |
Pending (100002) |
exchanging, until GTR reports the result. |
Denied (200001, 200003, 200007, 100028, 100031 or 100034) |
rejected, with rejection.reason GTR_ and the code, such as GTR_200003. |
| Any other answer, or an incomplete verification | exchanging, then held for review (compliance pending) at the next status check. |
| None: the answer was lost | exchanging. The request is never sent again. |
Covalent reads a GTR transfer's status after each GTR callback about it, and once a minute while it is exchanging or awaiting_counterparty with no update for five minutes. Polling never fails a GTR transfer for lack of an answer.
To complete the transfer, report its blockchain transaction: PATCH /api/v2/transfers/:id with action accept and the txHash. The transfer must be awaiting_counterparty or accepted, with status.theirs accepted and compliance approved; otherwise the report is 400 INVALID_REQUEST. Covalent checks that GTR's status shows a completed verification (GTR: TRANSFER_NOT_AUTHORIZED if not), reports the hash to GTR (POST /api/verify/v2/notify_tx_id), and only then completes the transfer. A different hash already at GTR is GTR: TRANSACTION_CONFLICT.
VASP Discovery
Section titled “VASP Discovery”GTR's address search asks GTR's VASPs whether they hold the beneficiary address:
- Covalent reads GTR's VASP list, leaving out your own
vaspCode. - Four VASPs at a time, it asks GTR's router which VASP to check (
auto_address_vasp_detection), then asks that VASP to verify the address, asset, network and tag (verify_address). Each check's request ID is saved before it is sent: a check whose answer is lost is queried, never sent again. - While checks are pending, the transfer stays
processing, and Covalent searches again at least 11 seconds later. Discovery that has not resolved within five minutes fails the transfer. - When exactly one VASP confirms the address, GTR can carry the transfer to it. When none does, GTR has no recipient, and another provider may carry the transfer.
A VASP that GTR found is remembered for five minutes for the same address, asset, network and memo. Otherwise the search runs for every outgoing transfer while GTR is enabled and has credentials for the environment, alongside the other providers' discovery.
If the search ends in an error, the transfer fails and no provider carries it, even one that found the beneficiary VASP. The errors are: an asset and network GTR does not support; a failure reading GTR's VASP list, including a list of more than 500 VASPs, or asking its router; a check that answers an error, or does not match its request; more than one VASP confirming the address; a search more than five minutes old.
Incoming Transfers
Section titled “Incoming Transfers”When another VASP sends your customer a transfer through GTR:
- GTR checks the address with you (
callbackType10and6). See Callbacks. - GTR sends the originator VASP's IVMS101, encrypted for your
publicKey(callbackType4). The address must be exactly one verified wallet whose customer has a verified Travel Rule identity. Covalent decrypts the data and checks the beneficiary it names against that identity: the same persons, in order, with the same names (ignoring case, spacing and punctuation), and the same date of birth and national identifier where the data gives them. A mismatch is answered200003, and nothing is recorded. - Covalent records an incoming transfer,
exchanging, with anexpiresAt72 hours later, and answers GTR pending (100002). A repeated request records nothing new, and gets the decision once Covalent has sent one. - It then screens the originator data, and each additional person in it:
- approved: Covalent sends GTR its acceptance, with your customer's verified identity as the beneficiary and your company profile as the beneficiary VASP. The transfer moves to
awaiting_counterparty. - review: the transfer is
held, compliancepending, until you accept or reject it. - rejected: Covalent sends GTR a rejection, and the transfer is
rejected.
- approved: Covalent sends GTR its acceptance, with your customer's verified identity as the beneficiary and your company profile as the beneficiary VASP. The transfer moves to
- When the originator VASP reports the transaction (
callbackType7) and GTR's status confirms the hash, Covalent completes the transfer with thattxHash.
Accept and Reject
Section titled “Accept and Reject”Accept, reject and transaction reports on a GTR transfer use strict notification: Covalent sends the decision to GTR first, and changes the transfer only once GTR has taken it. When the decision is not allowed or cannot be delivered, PATCH /api/v2/transfers/:id answers 400 INVALID_REQUEST with the GTR error in error, such as GTR: DECISION_NOT_ALLOWED or GTR: TRANSPORT_ERROR, and the transfer is unchanged.
| Action | Transfer | GTR receives |
|---|---|---|
accept |
Incoming, held, compliance pending |
Your acceptance of its PII verification, with your customer's verified identity and your company profile. The transfer moves to awaiting_counterparty, compliance approved. |
reject |
Incoming, held, compliance pending |
A rejection of its PII verification. The transfer is rejected. |
accept with txHash |
Outgoing: see Outgoing Transfers | The transaction hash. The transfer is completed. |
Before it sends a decision on an incoming transfer, Covalent checks:
| Error | When |
|---|---|
GTR: DECISION_NOT_ALLOWED |
GTR's request no longer waits for your PII decision, a transaction hash is already recorded, or the transfer is final. |
GTR: COMPLIANCE_NOT_APPROVED |
An accept before Covalent has screened the originator data, or after screening rejected it. |
GTR: BENEFICIARY_CHANGED, GTR: BENEFICIARY_IDENTITY_CHANGED |
The wallet's customer, or that customer's verified identity, no longer matches the request. |
GTR: PEER_KEY_CHANGED |
The originator VASP's key in GTR's directory has changed. |
GTR: DECISION_REQUIRES_RECONCILIATION |
An earlier attempt to send a decision did not finish. Covalent does not send it again. |
The reason and details of a rejection stay in Covalent: GTR receives a fixed reason, Local compliance decision.
The API's reject does not apply to an outgoing GTR transfer. Covalent rejects one itself when screening of the beneficiary data rejects it: it ends the GTR request first (POST /api/verify/v2/end, reason type SECURITY_COMPLIANCE_FAIL). If GTR cannot be told, the transfer stays held with compliance rejected.
Connection Test
Section titled “Connection Test”POST /api/v2/providers/gtr/test checks the key's environment's credentials in this order, and stops at the first failure:
- Every field holds a value: else
Missing required fields: .... - The values are valid: else
GTR: INVALID_CONFIGURATION, or for the PII keysGTR: INVALID_KEY_OR_CIPHERTEXT,GTR: INVALID_PRIVATE_KEYorGTR: KEY_PAIR_MISMATCH. - Your company profile is complete and valid: else a message that names the fields to fix.
- GTR answers
GET /api/statuswith success, through the forwarder with your certificate: elseGTR: TRANSPORT_ERROR(the connection or TLS handshake failed),GTR: TIMEOUT,GTR: FORWARDER_UNAVAILABLE,GTR: HTTP_<status>, orGTR: VERIFY_<code>for any GTR answer but success.
A passing test does not check your PII keys against GTR's directory, your callback path or your callback proxy.
Known Limitations
Section titled “Known Limitations”- Not yet tested against GTR. No call has been made to GTR's UAT or production environment: that needs a certificate GTR has issued. The forwarder has been tested against a local stand-in for GTR that requires client certificates, and the path from the API to the forwarder container has been tested locally. With UAT credentials, save them with a test key, then run the connection test.
- Callbacks need your own mTLS proxy. Covalent never sees GTR's client certificate: it checks only the two proxy headers and the shared
callbackProxySecret. - No fixed outbound IP addresses. Calls to GTR do not come from fixed IP addresses, so GTR cannot allowlist them by source address. Check with GTR whether it requires that before you rely on the connection.
- GTR's search can stop routing. While GTR is enabled for an environment, an error in its address search fails the transfer whichever provider could carry it: for example a transfer on an asset and network GTR does not support, or any transfer while the search cannot reach GTR.
- Search capacity. The search checks four VASPs per pass, at least 11 seconds apart, within five minutes. A search over many VASPs may not finish in time.