> ## Documentation Index
> Fetch the complete documentation index at: https://developers.fireblocks.com/llms.txt
> Use this file to discover all available pages before exploring further.

# GTR

> Exchange Travel Rule data through Global Travel Rule (GTR) with the Fireblocks API: set up a legal entity and integration, create and encrypt Travel Rule messages, link them to transactions, and handle required actions and missing messages.

Global Travel Rule (GTR) exchanges Travel Rule data with counterparty VASPs for your incoming and outgoing transactions. You create a Travel Rule message (TRM) through the Fireblocks API, with the PII encrypted on your side, and link it to the Fireblocks transaction. Because Fireblocks does not hold the key that decrypts the PII, creating messages is API-only.

GTR is a premium add-on that Fireblocks Support enables on your workspace. It is available on Developer Sandbox, Testnet, and Mainnet workspaces. See [Travel Rule Overview](/docs/travel-rule-overview) for how Travel Rule fits into screening.

## What you can do through the API

| Task | Console | API |
| - | - | - |
| Configure Travel Rule rules | No: submit a policy template to Fireblocks Support | Read only |
| Set up the legal entity and integration | No | Yes |
| Create, link, and manage Travel Rule messages | No | Yes |

## How it works

Transactions pass through three policy stages:

| Stage | What it decides | Actions |
| - | - | - |
| Trigger (Screening Policy) | Whether the transaction needs Travel Rule review. | Screen (continue to the next stage) or pass (approve without review). |
| Missing Travel Rule Message Policy | What happens while a required message does not exist yet. | Wait, accept, or reject. Rules can depend on how long the transaction has been waiting, for example accepting small transactions after 30 minutes but rejecting large ones. |
| Outcome (Post-Screening Policy) | The final action once GTR returns a result. | Accept, reject, alert, or wait if the result is still pending. |

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](/api-reference/trlink/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

* **A GTR account** with a valid subscription, an API key and secret, and your VASP's public key configured in the GTR Dashboard. See [GTR's Fireblocks integration guide](https://www.globaltravelrule.com/documentation/connect-fireblocks-with-gtr).
* **Fireblocks Support** has enabled GTR on your workspace.
* **An ED25519 key pair.** You generate it and configure its public key in GTR. You use the private key to decrypt data you receive.

## 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](/reference/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 with [`POST /screening/trlink/customers`](/api-reference/trlink/create-customer):

| Field | Description |
| - | - |
| `shortName` | Required. |
| `fullLegalName` | The full registered name. |
| `countryOfRegistration` | ISO 3166-1 alpha-2 code, for example `US`. |
| `nationalIdentification` | National identifier, for example an EIN. |
| `dateOfIncorporation` | ISO date, for example `2020-01-15`. |
| `geographicAddress` | Registered address. |
| `vaults` | Vault account IDs this entity covers. |
| `discoverable` | Visibility in the partner's address book. `anonymous` (default): counterparties cannot see your entity details, but Fireblocks confirms the address exists. `hidden`: nothing is disclosed. `discoverable`: full details are shared. |

### Step 2: Create the integration

Create an integration between the legal entity and GTR with [`POST /screening/trlink/customers/integration`](/api-reference/trlink/create-customer-integration), passing the legal entity's `customerId` and GTR's `partnerIdent`. List partners and their identifiers with [`GET /screening/trlink/partners`](/api-reference/trlink/list-available-trsupport-partners).

The response returns a `customerIntegrationId`. Every Travel Rule call after this uses it.

### Step 3: Connect to GTR

Connect the integration with your GTR API key and secret, using [Connect customer integration](/api-reference/trlink/connect-customer-integration) (`PUT /screening/trlink/customers/integration/{customerIntegrationId}`). Fireblocks stores the credentials and returns them censored in later responses.

### Step 4: Test the connection

Call [`POST /screening/trlink/customers/integration/{customerIntegrationId}/test_connection`](/api-reference/trlink/test-connection). A `success` value of `true` confirms the integration can reach GTR.

## Encrypt PII for GTR

GTR requires all PII to be encrypted before it is sent; plain-text PII is rejected.

| | Value |
| - | - |
| Algorithm | Curve25519 |
| Key format | ED25519 key pair, converted to Curve25519 |
| Your public key | Configured in the GTR Dashboard |
| GTR's public key | From your GTR integration settings |

The public key endpoint used for [Sumsub](/docs/sumsub) (`.../public_key`) does not apply to GTR.

Use GTR's open-source encryption tool rather than implementing Curve25519 yourself. It handles the key conversion, encryption of outgoing IVMS101 data, and decryption of incoming data, independently of the Fireblocks SDK. See [GTR's Fireblocks integration guide](https://www.globaltravelrule.com/documentation/connect-fireblocks-with-gtr) for the tool.

The encrypted result goes in the TRM's `ivms101` object. The IVMS101 structure is the same as for other providers:

```json theme={"system"}
{
  "version": "IVMS101.2020",
  "data": "<encrypted IVMS101 data>",
  "filledFields": [
    "Originator.originatorPerson[].naturalPerson.name.nameIdentifier[].primaryIdentifier",
    "Beneficiary.beneficiaryPerson[].naturalPerson.name.nameIdentifier[].primaryIdentifier"
  ]
}
```

`filledFields` lists, in dot notation, every IVMS101 field you populated.

## Send an outgoing transaction

1. **Assess the requirement** with [Assess Travel Rule requirement](/api-reference/trlink/assess-travel-rule-requirement) (`POST .../trm/assess`), passing the amount, asset, source, destination, and `beneficiaryVaspId`. The `decision` is `REQUIRED`, `NOT_REQUIRED`, or `NEED_MORE_INFO`. When it is `REQUIRED`, `requiredFields` lists the IVMS101 fields to collect.
2. **Encrypt the PII** as described above.
3. **Create the TRM** with [`POST .../trm`](/api-reference/trlink/create-travel-rule-message), using the same transaction details and the `ivms101` object.
4. **Create the Fireblocks transaction** with `travelRuleMessageId` set to the TRM's `id`. If the transaction already exists, link the TRM with [`POST /screening/trlink/transaction/{txId}/travel_rule_message_id`](/api-reference/trlink/set-transaction-travel-rule-message-id).

```ts theme={"system"}
const { data: assessment } = await fireblocks.trLink.assessTRLinkTravelRuleRequirement({
  tRLinkAssessTravelRuleRequest: {
    amount: "1500",
    assetId: "ETH",
    direction: "OUTBOUND",
    source: { type: "VAULT_ACCOUNT", id: "0" },
    destination: { type: "ONE_TIME_ADDRESS", oneTimeAddress: { address: "0xabcd..." } },
    beneficiaryVaspId: "vasp-456",
  },
  customerIntegrationId,
});

if (assessment.decision === "REQUIRED") {
  const { data: trm } = await fireblocks.trLink.createTRLinkTrm({
    tRLinkCreateTrmRequest: {
      amount: "1500",
      assetId: "ETH",
      direction: "OUTBOUND",
      source: { type: "VAULT_ACCOUNT", id: "0" },
      destination: { type: "ONE_TIME_ADDRESS", oneTimeAddress: { address: "0xabcd..." } },
      beneficiaryVaspId: "vasp-456",
      ivms101: ivms, // encrypted IVMS101 object
    },
    customerIntegrationId,
  });

  await fireblocks.transactions.createTransaction({
    transactionRequest: {
      assetId: "ETH",
      amount: "1500",
      source: { type: "VAULT_ACCOUNT", id: "0" },
      destination: { type: "ONE_TIME_ADDRESS", oneTimeAddress: { address: "0xabcd..." } },
      travelRuleMessageId: trm.id,
    },
  });
}
```

## Receive an incoming transaction

1. **Assess the requirement**, passing the Fireblocks `txId` and the `originatorVaspId`. The transaction details are filled in from the `txId`.
2. **Encrypt the PII** you hold for your beneficiary.
3. **Create the TRM** with the `txId`, `originatorVaspId`, and `ivms101` object.
4. **Link the TRM** to the transaction with [`POST /screening/trlink/transaction/{txId}/travel_rule_message_id`](/api-reference/trlink/set-transaction-travel-rule-message-id).

## When a message needs more data

A TRM can enter `PENDING` 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](/docs/compliance-events-webhooks) for the full payload and how to subscribe.

| Action type | What to do |
| - | - |
| `UPLOAD_BENEFICIARY_PII` | Encrypt the beneficiary fields listed in `data.beneficiaryRequiredFields` and submit them. |
| `MANUAL_REVIEW` | A compliance review at GTR is needed. |

Read the current actions with [Get required actions for a TRM](/api-reference/trlink/get-required-actions-for-a-trm), and resolve them one at a time with [Resolve action for a TRM](/api-reference/trlink/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 a `TRLink.NoTRMessage` notification in the Compliance webhook category when this happens. See [Compliance Events & Webhooks](/docs/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`](/api-reference/trlink/manual-decision-for-missing-trm) 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 with [`POST /screening/trlink/transaction/{txId}/destination/travel_rule_message_id`](/api-reference/trlink/set-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}`.

| Task | Endpoint |
| - | - |
| Get a TRM's status and details | [`GET /trm/{trmId}`](/api-reference/trlink/get-trm-by-id) |
| Cancel a TRM and notify the counterparty | [`POST /trm/{trmId}/cancel`](/api-reference/trlink/cancel-travel-rule-message) |
| Redirect a TRM to a subsidiary VASP | [`POST /trm/{trmId}/redirect`](/api-reference/trlink/redirect-travel-rule-message) |
| List or get VASPs in GTR's directory | [`GET /vasps`](/api-reference/trlink/list-vasps), [`GET /vasps/{vaspId}`](/api-reference/trlink/get-vasp-by-id) |
| Check whether GTR supports an asset | [`GET /assets`](/api-reference/trlink/list-supported-assets), [`GET /assets/{assetId}`](/api-reference/trlink/get-supported-asset-by-id) |

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 before you test with real value. In the Console, Transaction History shows the policies and rules applied to each transaction, GTR's responses, and the final verdict with an explanation.

To update your GTR credentials later, submit a ticket to Fireblocks Support.

## Disconnect

[Disconnect customer integration](/api-reference/trlink/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}`](/api-reference/trlink/delete-customer)) also deletes its integrations, TRMs, and configuration. Neither action can be undone.

## On the Help Center

For GTR setup and monitoring in the Console, see [GTR](https://support.fireblocks.io/hc/en-us/articles/30614375972892-GTR).
