# token.transfer.final

Source: https://docs.settlemint.com/docs/events/token-transfer-final
Reference for the DALP token.transfer.final webhook event that confirms an indexed token transfer reached finality.



`token.transfer.final` tells a webhook consumer that DALP indexed a token transfer and the transfer passed the configured reorg depth.

Use this event to update downstream ledgers, reconciliation queues, and notification systems only after the transfer is no longer provisional.

The event is part of the token transfer lifecycle. Pending observations can arrive before block inclusion; final events confirm the indexed on-chain log after finality checks. Consumers should treat the event payload as the stable transfer record and use the delivery envelope for idempotent processing.

## Delivery contract [#delivery-contract]

| Field                           | Value                          |
| ------------------------------- | ------------------------------ |
| Event type                      | `token.transfer.final`         |
| Version                         | `1`                            |
| Lifecycle state                 | `final`                        |
| Counter-signed receipt required | `true`                         |
| SDK type                        | `Webhook.TokenTransferFinalV1` |

Related references:

* `idxr_token`: the indexed token that emitted the transfer.
* `idxr_transfer`: the indexed transfer row for the finalized log.

## When to consume this event [#when-to-consume-this-event]

Consume `token.transfer.final` when your integration needs a final transfer outcome rather than an early observation. Typical consumers include accounting exports, settlement reconciliation, investor notifications, and compliance monitoring systems that should not react to a transfer until the chain observation is final.

Do not use this event as a replacement for webhook verification. Verify the signature, timestamp, and event identifier before you process the payload.

Store `evt_id`, `request.idempotency_key` when present, and the transfer identifiers. These values keep a retry or replay from creating a duplicate downstream action.

See [webhook idempotency and on-chain outcome](/docs/events/idempotency-and-on-chain-outcome) for retry, replay, and lifecycle handling across pending, final, retracted, and recalled events.

## Payload fields [#payload-fields]

| Field             | Type             | Meaning                                                                                                        |
| ----------------- | ---------------- | -------------------------------------------------------------------------------------------------------------- |
| `tokenAddress`    | EVM address      | Token contract that emitted the transfer.                                                                      |
| `chainId`         | Integer          | EVM chain identifier for the indexed transfer.                                                                 |
| `from`            | EVM address      | Sender address recorded on the transfer log.                                                                   |
| `to`              | EVM address      | Recipient address recorded on the transfer log.                                                                |
| `amount`          | String           | Raw token amount from the transfer event. Interpret decimals from the token metadata used by your integration. |
| `transactionHash` | 32-byte EVM hash | Transaction that contained the transfer log.                                                                   |
| `blockNumber`     | Integer          | Block that contained the finalized transfer log.                                                               |
| `logIndex`        | Integer          | Log index of the transfer within the transaction receipt.                                                      |

## Payload schema [#payload-schema]

```json
{
  "type": "object",
  "properties": {
    "tokenAddress": {
      "type": "string",
      "pattern": "^0x[a-fA-F0-9]{40}$"
    },
    "chainId": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "from": {
      "type": "string",
      "pattern": "^0x[a-fA-F0-9]{40}$"
    },
    "to": {
      "type": "string",
      "pattern": "^0x[a-fA-F0-9]{40}$"
    },
    "amount": {
      "type": "string"
    },
    "transactionHash": {
      "type": "string",
      "pattern": "^0x[a-fA-F0-9]{64}$"
    },
    "blockNumber": {
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "logIndex": {
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "tokenAddress",
    "chainId",
    "from",
    "to",
    "amount",
    "transactionHash",
    "blockNumber",
    "logIndex"
  ],
  "additionalProperties": false
}
```

## TypeScript SDK example [#typescript-sdk-example]

```typescript
import { verifyWebhook, type Webhook } from "@settlemint/dalp-sdk";

const result = verifyWebhook({
  rawBody,
  headers,
  secret: process.env.DALP_WEBHOOK_SECRET!,
});

if (!result.ok) {
  throw new Error(`Webhook verification failed: ${result.code}`);
}

if (result.event.type === "token.transfer.final") {
  const event: Webhook.Event<"token.transfer.final"> = result.event;
  const { transactionHash, logIndex, amount } = event.payload;

  await recordFinalTransfer({
    eventId: event.evt_id,
    idempotencyKey: event.request?.idempotency_key,
    transactionHash,
    logIndex,
    amount,
  });
}
```

## curl example [#curl-example]

```bash
curl -X POST https://consumer.example.com/dalp/webhooks \
  -H "content-type: application/json" \
  -H "webhook-id: evt_docs_token_transfer_final_001" \
  -H "webhook-timestamp: 1778112000" \
  -H "webhook-signature: v1,docs-example-signature" \
  --data '{"evt_id":"evt_docs_token_transfer_final_001","type":"token.transfer.final","version":1,"lifecycle_state":"final","request":{"idempotency_key":"idem_01JZP7R5W8M9N0P1Q2R3S4T5"},"related":{"idxr_token":"idxr_token_example","idxr_transfer":"idxr_transfer_example"},"payload":{"tokenAddress":"0x5555555555555555555555555555555555555555","chainId":537001,"from":"0x6666666666666666666666666666666666666666","to":"0x7777777777777777777777777777777777777777","amount":"250000000000000000000","transactionHash":"0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc","blockNumber":18445240,"logIndex":7}}'
```

## Version history [#version-history]

* Version `1`: Initial registry entry for `token.transfer.final`.

## Deprecation [#deprecation]

This event type is not deprecated.

## Manifest [#manifest]

The machine-readable AsyncAPI entry is published in the [DALP events manifest](/.well-known/dalp-events.json).
