Payment Participants
Every payment record carries a top-level participants[] array that identifies the participants in the flow of funds other than your organization and records how each one was reconciled to a record in your workspace.
This is most valuable on inbound payments, where the sender is otherwise unknown to you. participants[] is how you learn who sent the funds, whether they were hosted by a custodian (VASP), and whether the supplied identity of the participant(s) matched your records. On outbound payments you have already supplied the participants (originator via desired.from.account_id and beneficiary via desired.to.account_id). So for outbound payments, the array reproduces your supplied participants and adds additional information about the destination wallet (for example, which VASP hosts it, if any).
Where Identity Data Comes From
Tesser obtains information for the participants[] from two sources:
- Travel Rule provider data (primary). When the payment is facilitated through a Travel Rule provider authorization flow. For inbound payments, information about the originator and originator VASP is obtained from the originator VASP. For outbound payments, information about the beneficiary and beneficiary VASP is obtained from the beneficiary VASP.
- Wallet screening entity attribution (fallback). When there is no Travel Rule provider-supplied data, Tesser uses the screening provider's entity attribution for the wallet when a named entity is identified. If both data sources are available, the Travel Rule data provider takes precedence.
Participant Roles
Each entry carries a role:
| Role | Meaning |
|---|---|
ORIGINATOR | The party ultimately instructing the funds transfer. |
ORIGINATOR_VASP | The VASP hosting the sending wallet (recorded on inbound flows). |
BENEFICIARY | The party receiving the funds. |
BENEFICIARY_VASP | The VASP hosting the destination wallet (recorded on outbound flows). |
CUSTODY_SERVICE | A third-party custody service in the flow (VASPs sometimes use one to custody their wallets). |
INTERMEDIARY_VASP | Any other intermediary VASP identified in the flow. |
CONTRACT | The counterparty wallet is a contract address (a token contract or protocol). |
A payment to or from a CONTRACT participant is always routed to manual review (risk_status = awaiting_decision) — direct interaction with a contract address is not expected behavior for end-user wallets.
Which Roles May Populate, by Scenario
For outbound payments, the ORIGINATOR and BENEFICIARY entries come from the account IDs you supplied (see below). Tesser treats your supplied participants as "canonical" records and never overrides them in the participants[] with data returned by the Travel Rule data provider or wallet screening provider.
However, for the BENEFICIARY role, where it's possible there can be a mismatch between the identity info your organization supplied and the info the Beneficiary VASP has on file (or the identity attributed by the wallet screening provider), Tesser will report the mismatch on the payment record so your organization can be aware (see below).
This table lays out the data source for each role, by outbound payment scenario:
| Scenario | ORIGINATOR | CUSTODY_SERVICE / INTERMEDIARY_VASP | BENEFICIARY | BENEFICIARY_VASP |
|---|---|---|---|---|
| Travel Rule provider-facilitated flow (VASP-hosted beneficiary) | Supplied by your organization | Populated from the Travel Rule data provider and/or wallet screening provider, if identified | Supplied by your organization | Populated from the Travel Rule data provider or wallet screening provider, if identified |
| On-chain transfer only, VASP-hosted beneficiary | Supplied by your organization | Populated from the wallet screening provider, if identified | Supplied by your organization | Populated from the wallet screening provider, if identified |
| On-chain transfer only, self-hosted beneficiary | Supplied by your organization | Populated from the wallet screening provider, if identified | Supplied by your organization | Not populated — a self-hosted wallet has no hosting VASP |
For inbound payments, the BENEFICIARY entry comes from the corresponding Counterparty (or Tenant) who owns the account ID that represents the wallet address the originator/originator VASP sends to.
Similar to outbound payments, Tesser treats your supplied identity info for the beneficiary as the canonical record and does not replace that role in the participants[] with data returned by the Travel Rule data or wallet screening provider.
However, when the flow is facilitated by a Travel Rule data provider, if there is a mismatch between the identity info your organization has on file for the beneficiary and the info the Beneficiary VASP supplied, Tesser will report the mismatch on the payment record so your organization can be aware (see below).
This table lays out the data source for each role, by inbound payment scenario:
| Scenario | ORIGINATOR | ORIGINATOR_VASP | CUSTODY_SERVICE / INTERMEDIARY_VASP | BENEFICIARY |
|---|---|---|---|---|
| Travel Rule provider-facilitated flow (VASP-hosted sender) | Populated from the Travel Rule data provider | Populated from the Travel Rule data provider | Populated from the Travel Rule data provider and/or wallet screening provider, if identified | Populated from lookup of Counterparty/Tenant who owns the account that represents the destination wallet address |
| On-chain transfer only, VASP-hosted sender | Rarely populated — without Travel Rule data, the individual behind a VASP-hosted wallet typically cannot be identified. | Populated from the wallet screening provider entity attribution, if available | Populated from the wallet screening provider, if identified | Same as above. |
| On-chain transfer only, self-hosted sender | Populated from the wallet screening provider attribution (a CONTRACT entry instead, if the wallet is a contract address). | Not populated — a self-hosted wallet has no hosting VASP | Populated from the wallet screening provider, if identified | Same as above. |
Accounts and participants on inbound payments
participants[] identifies who sent the funds. The sending address is recorded separately: the first time Tesser records an inbound payment from a wallet address it has not seen before, it creates an unmanaged account (is_managed = false) to represent that address and assigns it to the placeholder counterparty for inbound senders. That account is what estimated.from.account_id references, and subsequent payments from the same address reuse it.
This happens for every unrecognized sending address, whether or not a provider named an entity — so a payment can carry a sending account and still have no ORIGINATOR entry in participants[]. It is also distinct from the Counterparty that name-matching may create (COUNTERPARTY_CREATED, below): that record represents a named entity a provider disclosed, not the address funds arrived from. See Receive an Inbound Payment to a Wallet.
The resource Object
Each participant entry carries a resource object describing the record it was reconciled to:
| Field | Description |
|---|---|
resource.resource_type | The kind of record: COUNTERPARTY; TENANT (the wallet belongs to one of your tenants directly); or WORKSPACE (funds are moving to or from one of your own treasury wallets). |
resource.id | Identifier of the record the participant was reconciled to. |
resource.name_match_score | The name-match score, 0–100. null where no name matching applied. |
resource.name_match_threshold | The configured score above which a record is considered matched. null where no name matching applied. |
resource.name_match_comparison_id | The ID of the record whose name most closely matched the supplied name — the record the score was computed against. null where no name matching applied. |
resource.resolution | The reconciliation outcome. See below. |
The resolution values are:
EXACT_MATCH— the supplied name matched a record perfectly.PARTIAL_MATCH— reserved for future use. The match score exceeded the threshold but the match was not exact. This value remains in the API enum to support future fuzzy matching, but because name matching is currently exact-only, it is not returned today — a name either matches exactly or does not.DID_NOT_MATCH— a provider supplied a name for a participant you had already identified, and it scored at or below the threshold against your record. This is the mismatch signal: your record stays canonical and Tesser does not create a second one for it. On an inbound Travel Rule flow, it is also how a rejected authorization appears on the payment record.COUNTERPARTY_CREATED— Tesser discovered this participant from provider data, found no record of it in your workspace — either nothing matched, or the closest record scored at or below the threshold — and created a new Counterparty to represent it. Only discovered roles can carry this value; which roles those are depends on the direction of the payment (see the tables below). A participant you supplied never carries it.USER_SUPPLIED_ID— the participant was identified from an account on the payment rather than from provider data, so no name matching ran: the account ID your organization supplied (outbound), or the destination account of an inbound transfer. ABENEFICIARYentry also carries this value when no provider-supplied name was available to match at all — for example, an inbound payment that arrived with no Travel Rule data. No name matching applied, so the score, threshold, and comparison ID arenull.
Reconciling data from Travel Rule and wallet screening providers to your records
Tesser reconciles the entity data supplied by the Travel Rule data provider and/or wallet screening provider to existing records by name-matching.
Name matching exists to resolve the participants you could not have told us about. Whether a role is name-matched at all — and whether it can produce a new Counterparty record — depends on whether you already knew that participant when the payment was created:
- Participants you supplied are canonical. On an outbound payment you supply both ends of the flow: the
ORIGINATOR(your end user) and theBENEFICIARYyou intend to pay. On an inbound payment you know theBENEFICIARY— it is the Counterparty or Tenant that owns the destination account. Tesser never overwrites these records and never creates a new one for them. Where a provider does supply a name for one of these roles, matching runs for a single purpose: to tell you whether the provider's name agrees with yours. - Participants Tesser discovers come from provider data. On an outbound payment you know who you are paying, but not whether a VASP hosts that wallet or which one — so the
BENEFICIARY_VASPis an unknown party, as are anyCUSTODY_SERVICEorINTERMEDIARY_VASPin the flow. On an inbound payment the unknown parties are theORIGINATORandORIGINATOR_VASP, plus anyCUSTODY_SERVICEorINTERMEDIARY_VASP. These are the only roles matched against your full set of Counterparty and Tenant records, and the only roles for which Tesser will create a new Counterparty.
Names are matched exactly. Data is matched against your counterparty and tenant records and scored 0–100. An "exact" match means the match threshold is 99, which must be exceeded (i.e. score = 100).
Depending on the participant role and the direction of the payment, Tesser may create a new counterparty record (resolution = COUNTERPARTY_CREATED) and populate participants[] with that record if we have never seen an entity before or if an entity fails the name match check. When name matching is happening for canonical records, we will identify the mismatch between your information and the data provider's information (DID_NOT_MATCH).
Not all participants will have name-matching conducted. See the below tables for which roles may be name-matched for each payment direction.
This table outlines how name-matching works for outbound payments.
| Role | Known to you? | Data universe for match | Potential resolution values |
|---|---|---|---|
ORIGINATOR | Yes — you supplied it | N/A (Name matching cannot be performed) | USER_SUPPLIED_ID |
CUSTODY_SERVICE / INTERMEDIARY_VASP | No — discovered by Tesser | All Counterparty and Tenant records | EXACT_MATCH, COUNTERPARTY_CREATED |
BENEFICIARY | Yes — you supplied it | Counterparty record that owns the desired.to.account_id | EXACT_MATCH, DID_NOT_MATCH, USER_SUPPLIED_ID (populated when name matching not performed on Beneficiary name) |
BENEFICIARY_VASP | No — discovered by Tesser | All Counterparty and Tenant records | EXACT_MATCH, COUNTERPARTY_CREATED |
This table outlines how name-matching works for inbound payments.
| Role | Known to you? | Data universe for match | Potential resolution values |
|---|---|---|---|
ORIGINATOR | No — discovered by Tesser | All Counterparty and Tenant records | EXACT_MATCH, COUNTERPARTY_CREATED |
ORIGINATOR_VASP | No — discovered by Tesser | All Counterparty and Tenant records | EXACT_MATCH, COUNTERPARTY_CREATED |
CUSTODY_SERVICE / INTERMEDIARY_VASP | No — discovered by Tesser | All Counterparty and Tenant records | EXACT_MATCH, COUNTERPARTY_CREATED |
BENEFICIARY | Yes — from your destination account | Counterparty or Tenant record that owns the estimated.to.account_id | EXACT_MATCH, DID_NOT_MATCH, USER_SUPPLIED_ID (populated when name matching not performed on Beneficiary name) |
When participants[] Populates
participants[] is populated once; when depends on the flow. It may be populated before or along with funding_account_id, *.from.account_id, and *.to.account_id.
| Flow | When participants[] populates | When account ids populated |
|---|---|---|
| Inbound, Travel Rule authorization flow | At payment record creation, before funds move | After funds move on-chain |
| Inbound, on-chain transfer only | After funds move on-chain, once wallet screening completes | After funds move on-chain |
| Outbound | Your supplied entries at creation; a BENEFICIARY_VASP entry once screening completes. | At payment record creation |
Examples
Inbound — Travel Rule authorization flow. The originator could not be matched to any existing record (a new counterparty was created), and the originator's VASP and the beneficiary each matched an existing record exactly:
Code
Inbound — on-chain transfer only, VASP-hosted sender. No Travel Rule data accompanied the transfer, so no originator entry is possible. Screening attributes the sending wallet to a VASP whose name didn't exactly match an existing counterparty, so a new counterparty was created. The beneficiary is identified from the destination account — with no Travel Rule data there is no beneficiary name to match, so it carries USER_SUPPLIED_ID:
Code
Outbound — destination attributed to a VASP. Your supplied originator and beneficiary are recorded as-is; screening identified the VASP hosting the destination wallet:
Code
Raw Travel Rule Data
For payments that arrived through a Travel Rule authorization flow, the raw transfer record — including the originator and beneficiary identity data exactly as the sending VASP transmitted it — is passed through on the payment in provider_metadata[], in the entry with provider_metadata_type = TRAVEL_RULE. It is preserved regardless of the match outcome, so you can run your own screening and monitoring on the original data and compare it against the record the payment was reconciled to.
Each provider_metadata[] entry has three fields:
| Field | Description |
|---|---|
provider_metadata_type | What the payload is: TRAVEL_RULE or WALLET_RISK_SCREENING. |
provider_metadata_key | The provider that produced it. |
provider_metadata_data | The raw provider payload. |
The WALLET_RISK_SCREENING entry is covered in Wallet Risk Screening Data.