> For the complete documentation index, see [llms.txt](https://docs.t-rex.network/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.t-rex.network/guides/issuer/04.-add-a-trusted-claim-issuer.md).

# 04. Add a trusted Claim Issuer

Adding a trusted Claim Issuer tells the asset whose attestations count. The Issuer names a Claim Issuer in its eligibility registry, together with the claim topics it trusts that issuer for. From then on, a valid claim signed by that issuer for one of those topics satisfies the asset's requirement for the topic. The Issuer does this before the first mint, and whenever it starts relying on a new provider.

## At a glance

|                   |                                                                                                                                                                                                                                                                                                                                                                                                                     |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Triggered by**  | Issuer                                                                                                                                                                                                                                                                                                                                                                                                              |
| **Actors**        | Issuer, Claim Issuer, Investor, Platform                                                                                                                                                                                                                                                                                                                                                                            |
| **Contracts**     | `TREXRegistry`, the ONCHAINID of the Claim Issuer (read only, during verification)                                                                                                                                                                                                                                                                                                                                  |
| **Preconditions** | The token suite is deployed (see [01](/guides/issuer/01.-deploy-a-token-suite.md)); the caller holds `OWNER` in the asset's domain (see [25](/guides/issuer/25.-commission-a-suite-and-grant-roles.md)); the Claim Issuer has an ONCHAINID of type `CLAIM_ISSUER` with `CLAIM_SIGNER` keys, or is an adapter contract that answers `isClaimValid`; the Issuer has concluded its own agreement with the Claim Issuer |
| **Result**        | `TREXRegistry` lists the Claim Issuer as trusted for the given topics, and its valid claims count toward eligibility for the asset                                                                                                                                                                                                                                                                                  |

## Actors and roles

| Actor        | Role in this flow                                                                | What they hold                                       |
| ------------ | -------------------------------------------------------------------------------- | ---------------------------------------------------- |
| Issuer       | Decides to rely on the Claim Issuer and submits the change.                      | `OWNER` on the `TREXRegistry`                        |
| Claim Issuer | Becomes trusted for the asset. Does not transact in this flow.                   | Its ONCHAINID, and the keys that sign its claims     |
| Investor     | Is affected: claims it holds from this issuer start to count. Does not transact. | An ONCHAINID carrying claims                         |
| Platform     | Runs the reads and submits with the Issuer's key.                                | The Issuer's signing key, or a key authorized for it |

## Sequence

```mermaid
sequenceDiagram
    participant Platform
    participant Issuer
    participant Registry as TREXRegistry

    Platform->>Registry: isTrustedIssuer(claimIssuer) (read)
    Platform->>Registry: getTrustedIssuers() (read)
    Platform->>Issuer: checks passed, submit
    Issuer->>Registry: addTrustedIssuer(claimIssuer, claimTopics)
    Registry->>Registry: caller holds OWNER
    Registry->>Registry: issuer not zero, not already trusted, topics valid, registry not full
    Registry-->>Platform: TrustedIssuerAdded(claimIssuer, claimTopics)
    opt the topics of a trusted issuer change later
        Issuer->>Registry: updateIssuerClaimTopics(claimIssuer, claimTopics)
        Registry-->>Platform: ClaimTopicsUpdated(claimIssuer, claimTopics)
    end
```

## Step by step

### Step 1. Check the Claim Issuer and the registry

**Who:** Platform, on behalf of the Issuer

**Call:** Off-chain, using read calls

**Before the call:** The Issuer has the address of the Claim Issuer and the list of topics it trusts that issuer for. The address is the Claim Issuer's ONCHAINID, not the key it signs with.

**What happens:** The Platform reads `TREXRegistry.isTrustedIssuer(claimIssuer)`, which must be false, and `TREXRegistry.getTrustedIssuers()`, whose length must be below 50. It confirms that the address is the contract the Claim Issuer answers from: for an ONCHAINID, `IdentityFactory.identityTypeOf(claimIssuer)` returns `CLAIM_ISSUER`. The registry does not make this check. The Issuer does. The recommendation is to trust only identities the factory created with that type, and adapters governed by Network governance.

**What changes:** Nothing on-chain.

### Step 2. Add the trusted issuer

**Who:** Issuer (`OWNER`)

**Call:** `TREXRegistry.addTrustedIssuer(trustedIssuer, claimTopics)`

**Before the call:** Step 1 passed.

**What the contract checks:**

1. The caller holds `OWNER` in the asset's domain. Otherwise the call reverts with `AccessManagedUnauthorized`.
2. `trustedIssuer` is not the zero address. Otherwise `ZeroAddress`.
3. The issuer is not already trusted. Otherwise `TrustedIssuerAlreadyExists`.
4. `claimTopics` is not empty. Otherwise `TrustedClaimTopicsCannotBeEmpty`.
5. `claimTopics` holds at most 15 topics. Otherwise `MaxClaimTopicsReached`.
6. The registry holds fewer than 50 trusted issuers. Otherwise `MaxTrustedIssuersReached`.

**What changes:** The registry records the issuer and, for each topic, that this issuer is trusted for it. It emits `TrustedIssuerAdded(trustedIssuer, claimTopics)`. From the next eligibility check, a valid claim from this issuer for one of these topics satisfies the topic, for every identity that holds one.

### Step 3. Change the topics of a trusted issuer

Optional, and later in the life of the asset.

**Who:** Issuer (`OWNER`)

**Call:** `TREXRegistry.updateIssuerClaimTopics(trustedIssuer, claimTopics)`

**Before the call:** The Issuer has the complete new list. The call replaces the list. It does not add to it.

**What the contract checks:**

1. The caller holds `OWNER`. Otherwise `AccessManagedUnauthorized`.
2. `trustedIssuer` is not zero and is a trusted issuer. Otherwise `ZeroAddress` or `NotATrustedIssuer`.
3. `claimTopics` holds at most 15 topics and is not empty. Otherwise `MaxClaimTopicsReached` or `ClaimTopicsCannotBeEmpty`.

**What changes:** The issuer is trusted for the new list and for nothing else. The registry emits `ClaimTopicsUpdated(trustedIssuer, claimTopics)`. Claims from this issuer under a topic that left the list stop counting for the asset.

## State after the flow

* `TREXRegistry.isTrustedIssuer(claimIssuer)` is true.
* `TREXRegistry.getTrustedIssuerClaimTopics(claimIssuer)` returns the topics, and `TREXRegistry.hasClaimTopic(claimIssuer, topic)` is true for each.
* `TREXRegistry.getTrustedIssuersForClaimTopic(topic)` includes the issuer for each of its topics.
* `TREXRegistry.isVerified(address)` now counts this issuer's valid claims. An identity that was missing a topic and holds such a claim becomes eligible without any other transaction.
* Nothing has changed on any identity, and the list of required topics is unchanged.

## Failure modes

| Symptom                                                                      | Cause                                                                                                                                  | Fix                                                                                                                                             |
| ---------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| Reverts with `AccessManagedUnauthorized`                                     | The caller does not hold `OWNER` in the asset's domain (check 1)                                                                       | Grant the role: [25](/guides/issuer/25.-commission-a-suite-and-grant-roles.md)                                                                  |
| Reverts with `ZeroAddress`                                                   | The issuer address is zero (step 2, check 2)                                                                                           | Pass the Claim Issuer's ONCHAINID                                                                                                               |
| Reverts with `TrustedIssuerAlreadyExists`                                    | The issuer is already trusted (step 2, check 3)                                                                                        | Use `updateIssuerClaimTopics` to change its topics                                                                                              |
| Reverts with `TrustedClaimTopicsCannotBeEmpty` or `ClaimTopicsCannotBeEmpty` | No topic was given (step 2, check 4; step 3, check 3)                                                                                  | Give at least one topic. To stop trusting an issuer entirely, remove it: [20](/guides/issuer/20.-remove-a-trusted-claim-issuer.md)              |
| Reverts with `MaxClaimTopicsReached`                                         | More than 15 topics for one issuer (step 2, check 5; step 3, check 3)                                                                  | Reduce the list                                                                                                                                 |
| Reverts with `MaxTrustedIssuersReached`                                      | The registry already holds 50 issuers (step 2, check 6)                                                                                | Remove an issuer that is no longer used                                                                                                         |
| Reverts with `NotATrustedIssuer`                                             | `updateIssuerClaimTopics` on an issuer that was never added (step 3, check 2)                                                          | Add it first                                                                                                                                    |
| The issuer is trusted and investors remain ineligible                        | The topic is not in the issuer's list, the investors hold no claim from this issuer, or the claims are expired or revoked              | Compare `getTrustedIssuerClaimTopics` with `getClaimTopics`. Have claims issued: [05](/guides/claim-issuer/05.-issue-a-claim-to-an-investor.md) |
| The issuer is trusted and its claims never validate                          | The address added is not the contract that answers `isClaimValid` for those claims, for example a signing key instead of the ONCHAINID | Remove it ([20](/guides/issuer/20.-remove-a-trusted-claim-issuer.md)) and add the right address                                                 |

## Common misunderstandings

> **Wrong:** "A trusted issuer is trusted for the asset."
>
> **Right:** It is trusted for the topics listed next to it, and for nothing else. A provider trusted for `<KYC topic>` does not satisfy `<accreditation topic>`, however valid its claim.

> **Wrong:** "Adding a trusted issuer makes its clients eligible."
>
> **Right:** It makes their claims count. An investor is eligible when its identity holds a valid claim, from a trusted issuer, for every required topic. Trusting an issuer for one topic changes nothing for the others.

> **Wrong:** "The Issuer adds the KYC provider's wallet."
>
> **Right:** The Issuer adds the Claim Issuer's ONCHAINID, or the adapter contract that answers for the claims. The registry asks that contract whether each claim is valid. The keys that sign claims are registered on that identity, and the Claim Issuer rotates them without the Issuer changing anything.

> **Wrong:** "An issuer with a high reputation in the network is trusted by every asset."
>
> **Right:** Reputation decides whether a Claim Issuer can write its claims onto identities without a key grant. It gives no eligibility. Each asset counts only the issuers in its own registry.

## Integration notes

* Add the trusted issuer before requiring a topic that only it can satisfy. See [03](/guides/issuer/03.-configure-required-claim-topics.md).
* `updateIssuerClaimTopics` replaces the whole list. Read `getTrustedIssuerClaimTopics` first and send the complete new list.
* The registry does not verify what the address is. Check the type in the `IdentityFactory`, or the adapter's configuration, before adding it. A Claim Issuer that comes from another source is unlikely to be accepted by the other participants of the ecosystem.
* Verification asks each trusted issuer of a topic in turn. A short list of issuers per topic keeps `isVerified` cheap on every transfer.
* Index `TrustedIssuerAdded`, `TrustedIssuerRemoved` and `ClaimTopicsUpdated` to keep an off-chain view of whom the asset trusts.
* An external attestation system is trusted the same way: the adapter's address is added as a trusted issuer. See [External attestations](/identity-onchainid/external-attestations.md).

## Related flows

* [03 Configure required claim topics](/guides/issuer/03.-configure-required-claim-topics.md) : which topics the asset requires
* [01 Deploy a token suite](/guides/issuer/01.-deploy-a-token-suite.md) : sets the first trusted issuers
* [20 Remove a trusted Claim Issuer](/guides/issuer/20.-remove-a-trusted-claim-issuer.md) : the inverse operation
* [05 Issue a claim to an investor](/guides/claim-issuer/05.-issue-a-claim-to-an-investor.md) : what a trusted issuer then does
* [19 Revoke a claim](/guides/claim-issuer/19.-revoke-a-claim.md) : how a trusted issuer withdraws an attestation


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.t-rex.network/guides/issuer/04.-add-a-trusted-claim-issuer.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
