# 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). |

:::note
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:**

<div className="balanced-table first-col-26">

| 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 |

</div>

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:**

<div className="balanced-table first-col-26">

| 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. |

</div>

:::note{title="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](/how-tos/receive-an-inbound-payment-to-a-wallet#sending-wallet-account-handling).
:::

## 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. A `BENEFICIARY` entry 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 are `null`.

## 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 the `BENEFICIARY` you intend to pay. On an inbound payment you know the `BENEFICIARY` — 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_VASP` is an unknown party, as are any `CUSTODY_SERVICE` or `INTERMEDIARY_VASP` in the flow. On an inbound payment the unknown parties are the `ORIGINATOR` and `ORIGINATOR_VASP`, plus any `CUSTODY_SERVICE` or `INTERMEDIARY_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`).

:::note
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.**

<div className="balanced-table name-match-cols">

| 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` |

</div>

**This table outlines how name-matching works for inbound payments.**

<div className="balanced-table name-match-cols">

| 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) |

</div>

## 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`.

<div className="balanced-table first-col-26">

| 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 |

</div>

## 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:

```json
{
  "participants": [
    {
      "role": "ORIGINATOR",
      "resource": {
        "resource_type": "COUNTERPARTY",
        "id": "3c9a1e57-8b2f-4d06-9e41-7a5c2f8d1b60",
        "name_match_score": "23",
        "name_match_threshold": "99",
        "name_match_comparison_id": "b41f7c29-6d83-45ea-a1c7-9f20d3e8b574",
        "resolution": "COUNTERPARTY_CREATED"
      }
    },
    {
      "role": "ORIGINATOR_VASP",
      "resource": {
        "resource_type": "COUNTERPARTY",
        "id": "7d2e9f44-1a6b-4c58-8e03-b5f19c72a3d8",
        "name_match_score": "100",
        "name_match_threshold": "99",
        "name_match_comparison_id": "7d2e9f44-1a6b-4c58-8e03-b5f19c72a3d8",
        "resolution": "EXACT_MATCH"
      }
    },
    {
      "role": "BENEFICIARY",
      "resource": {
        "resource_type": "COUNTERPARTY",
        "id": "e8b3d016-4f7a-49c2-95d8-2c61a0f9e735",
        "name_match_score": "100",
        "name_match_threshold": "99",
        "name_match_comparison_id": "e8b3d016-4f7a-49c2-95d8-2c61a0f9e735",
        "resolution": "EXACT_MATCH"
      }
    }
  ]
}
```

**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`:

```json
{
  "participants": [
    {
      "role": "ORIGINATOR_VASP",
      "resource": {
        "resource_type": "COUNTERPARTY",
        "id": "b8b8fc6c-62b5-4617-bc45-28ac30456f49",
        "name_match_score": "89",
        "name_match_threshold": "99",
        "name_match_comparison_id": "f6a2c81d-3e97-4b5a-a24e-8c1d0b9e6f42",
        "resolution": "COUNTERPARTY_CREATED"
      }
    },
    {
      "role": "BENEFICIARY",
      "resource": {
        "resource_type": "COUNTERPARTY",
        "id": "e8b3d016-4f7a-49c2-95d8-2c61a0f9e735",
        "name_match_score": null,
        "name_match_threshold": null,
        "name_match_comparison_id": null,
        "resolution": "USER_SUPPLIED_ID"
      }
    }
  ]
}
```

**Outbound — destination attributed to a VASP.** Your supplied originator and beneficiary are recorded as-is; screening identified the VASP hosting the destination wallet:

```json
{
  "participants": [
    {
      "role": "ORIGINATOR",
      "resource": {
        "resource_type": "COUNTERPARTY",
        "id": "1f7d0a92-5c34-4b8e-9d16-8e2a4c7b3f50",
        "name_match_score": null,
        "name_match_threshold": null,
        "name_match_comparison_id": null,
        "resolution": "USER_SUPPLIED_ID"
      }
    },
    {
      "role": "BENEFICIARY",
      "resource": {
        "resource_type": "COUNTERPARTY",
        "id": "e8b3d016-4f7a-49c2-95d8-2c61a0f9e735",
        "name_match_score": null,
        "name_match_threshold": null,
        "name_match_comparison_id": null,
        "resolution": "USER_SUPPLIED_ID"
      }
    },
    {
      "role": "BENEFICIARY_VASP",
      "resource": {
        "resource_type": "COUNTERPARTY",
        "id": "a4c1f0b8-2e9d-4a63-b7c5-1d8f6e0a3c92",
        "name_match_score": "100",
        "name_match_threshold": "99",
        "name_match_comparison_id": "a4c1f0b8-2e9d-4a63-b7c5-1d8f6e0a3c92",
        "resolution": "EXACT_MATCH"
      }
    }
  ]
}
```

## 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](/overviews/wallet-risk-screening#raw-screening-data).
