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

# Read Canton Transactions

> Canton items are standard Fireblocks transactions. Read them with the existing transactions endpoints and branch on the cantonDetails object.

Canton items are Fireblocks transactions, not a separate resource tree. There are no Canton-specific read endpoints. You list and read Canton activity with the transactions endpoints you already use, and everything Canton-specific arrives in a `cantonDetails` object on the transaction.

| What you want | Endpoint |
| - | - |
| List or filter Canton items | [`GET /v1/transactions`](/api-reference/transactions/get-transaction-history) |
| Read one Canton item | [`GET /v1/transactions/{txId}`](/api-reference/transactions/get-a-specific-transaction-by-fireblocks-transaction-id) |

The webhook carries the identical `cantonDetails` object, so a client that handles one needs no second parser for the other. See [Canton Transaction Webhooks](/docs/canton-transaction-webhooks).

## Identify a Canton transaction

The presence of `cantonDetails` is the authoritative signal that a transaction is a Canton item. A transaction with no `cantonDetails` object is not one.

## The three shapes of cantonDetails

At most one of these three keys is present on any transaction.

| Key | Meaning |
| - | - |
| `cantonDetails.offerResponse` | This transaction belongs to an offer conversation: the offer, the answer to it, or a leg that cannot be answered. |
| `cantonDetails.call` | This transaction is a call you made. |
| `cantonDetails.settlement` | A venue settled an allocation. This is the credit side of a delivery-versus-payment. |

The split is not inbound versus outgoing. Every response transaction you create is outgoing and carries `offerResponse`, and in the vault-to-vault transfer case a pre-existing outgoing transfer is stamped with a populated `availableResponses`.

If `cantonDetails` is present but none of the three keys are, the transaction is Canton-related but outside these shapes. Skip it rather than treating it as an error.

## Decide whether an offer can be responded to

This is the rule the rest of the page depends on.

<Warning>
  A transaction is answerable if and only if `cantonDetails.offerResponse.availableResponses` is non-empty. Never decide answerability from `subStatus == PENDING_RECEIVER_APPROVAL`.
</Warning>

One offer can flag two transactions with `PENDING_RECEIVER_APPROVAL`. In the vault-to-one-time-address transfer case you see this:

```text theme={"system"}
tx A   PENDING_RECEIVER_APPROVAL   availableResponses [TRANSFER_ACCEPT, TRANSFER_REJECT]
tx B   PENDING_RECEIVER_APPROVAL   availableResponses []
                                   originalTransactionId → tx A
```

A client that filters on the sub-status posts to both and gets a `409` on the second. A client that filters on `availableResponses.length > 0` posts once. Transaction B is neither broken nor a duplicate. It is a linked leg whose only job is to point at where the answer goes.

```javascript theme={"system"}
const answerable = transactions.filter(
  (tx) => (tx.cantonDetails?.offerResponse?.availableResponses?.length ?? 0) > 0
);
```

An empty `availableResponses` means nothing is answerable here. It does not always mean the offer is closed: on a linked leg it means answer elsewhere, and `originalTransactionId` says where. The array going empty is also the terminal signal, covering answered, expired, and a response in flight. There is no separate resolved flag.

## Fields on offerResponse

| Field | Required | Description |
| - | - | - |
| `version` | Yes | Schema version of this object. Currently `1`. |
| `domain` | Yes | `ONBOARDING`, `ALLOCATIONS`, or `TRANSFERS`. Copy this value straight into the `domain` field of your response body. |
| `availableResponses` | Yes | Response identifiers you can exercise on this transaction right now. Identifiers only, never a schema. |
| `vendor` | No | `DTCC` or `TRADEWEB`. Absent means vendor-neutral, not unknown. Allocations and transfers have no vendor. |
| `expiresAt` | No | RFC 3339 date-time when the offer expires if unanswered. Absent on offer types that carry no deadline. |
| `approvalTransactionId` | No | Set on the offer transaction once a response is dispatched. Names the outgoing response transaction. |
| `originalTransactionId` | No | Set on the response transaction, pointing back at the offer it answered, and on a linked leg, pointing at where the answer belongs. |
| `verdict` | No | `ACCEPTED` or `REJECTED`. Reflects the answer submitted, not whether the chain accepted it. The transaction status carries that. |

<Note>
  Not every offer has a deadline, so treat `expiresAt` as optional. Where it is present and passes, the transaction moves to sub-status `RECEIVER_APPROVAL_TIMEOUT` and `availableResponses` empties.
</Note>

`availableResponses` carries identifiers, not argument shapes. What each value means, and which fields it requires, lives in the matching variant of the request schema on [Answer an offer](/api-reference/canton-beta/answer-an-offer). Treat the enum as open: a new vendor flow adds a value, so tolerate values you do not recognize rather than failing to deserialize.

## Answer an offer

Take `id` from the answerable transaction. That is the `offerId` path parameter of [Answer an offer](/api-reference/canton-beta/answer-an-offer).

```http theme={"system"}
POST /v1/operations/canton/offers/{offerId}/responses
```

Copy `cantonDetails.offerResponse.domain` into the body's `domain`, then pick a `responseType` from `availableResponses`.

```json theme={"system"}
{
  "domain": "ONBOARDING",
  "response": {
    "responseType": "DTCC_END_INVESTOR_ONBOARDING_ACCEPT"
  }
}
```

## Fields on call

Present on an outgoing transaction that carries a call you made with [Make a Canton call](/api-reference/canton-beta/make-a-canton-call). This makes `GET /v1/transactions` filterable into your Canton calls without a per-call-type collection endpoint.

| Field | Required | Description |
| - | - | - |
| `version` | Yes | Schema version. Currently `1`. |
| `domain` | Yes | The domain this call operates on. |
| `type` | Yes | Which call this transaction carries, such as `DTCC_PARTICIPANT_ONBOARDING` or `ALLOCATION_WITHDRAW`. |
| `vendor` | No | Absent on the vendor-neutral calls, `ALLOCATION_WITHDRAW` and `TRANSFER_WITHDRAW`. |
| `originalTransactionId` | No | The transaction this call acts on. Present only on `ALLOCATION_WITHDRAW` and `TRANSFER_WITHDRAW`. |

`domain` is derivable from `type`, but it is published so that filtering for all your onboarding activity is one filter across offers and calls rather than an eight-entry mapping each client reimplements.

## Fields on settlement

Present on the settlement receipt, the transaction that appears when a venue executes an allocation you had locked. It is `COMPLETED` at creation and carries the cross leg: the asset and amount you receive, where the allocation transaction carried what you gave.

| Field | Required | Description |
| - | - | - |
| `version` | Yes | Schema version. Currently `1`. |
| `domain` | Yes | Always `ALLOCATIONS` today. |
| `type` | Yes | `ALLOCATION_SETTLEMENT`. |
| `originalTransactionId` | Yes | The allocation transaction this receipt settles. |

Without `originalTransactionId` the credit side of a delivery-versus-payment is an unexplained incoming transfer, and the two halves of one trade cannot be reconciled through the API.

## The ALLOCATED lifecycle

An accepted allocation is the one place a Canton transaction sits at `CONFIRMING` for an extended period rather than passing through it:

```text theme={"system"}
status CONFIRMING · subStatus ALLOCATED     locked on chain, withdrawable
        ↓ venue settles                     ↓ withdraw succeeds
status COMPLETED                            status CANCELLED
```

`CONFIRMING` with `ALLOCATED` is the only state in which `ALLOCATION_WITHDRAW` accepts the transaction, and that transaction's `id` is what you pass as `allocationTransactionId` to [Make a Canton call](/api-reference/canton-beta/make-a-canton-call).

## Amounts

`amount` is a decimal string, not a number. Token amounts exceed the precision of an IEEE 754 double, so a JSON number would round silently. Parse with a decimal library rather than `parseFloat`. Operations that move nothing, including onboarding, invites, and allow-list changes, carry `"0"`.
