# Token permits

Source: https://docs.settlemint.com/docs/developers/api-integration/token-permits
Read EIP-2612 permit metadata and relay signed permit approvals for DALP asset tokens.



Token permits let a holder approve a spender with an EIP-2612 signature instead of sending an on-chain approval transaction from the holder wallet. DALP exposes one read endpoint for permit metadata and one mutation endpoint that relays a signed permit through the transaction queue.

Use this API for allowance-based flows where the holder should not submit a separate `approve()` transaction. The holder signature authorizes the allowance. The authenticated caller relays the signed permit, and the caller's sender wallet pays for the queued transaction. A permit only sets an allowance. Any later transfer still runs through the token's normal compliance and transfer checks.

## Prerequisites [#prerequisites]

* A deployed token address with the permit feature attached.
* A holder wallet that can sign an EIP-2612 permit message for that token.
* The spender address, token amount, deadline, and signature parts (`v`, `r`, `s`).
* API authentication for the caller that submits the relay request.
* A caller participant with a sender wallet that DALP can use for the queued transaction.
* `walletVerification` for user-session relay requests. API-key requests authenticate the sender through the API key and do not send wallet verification fields.

## Permission boundary [#permission-boundary]

The permit mutation does not require a token access-control role because the EIP-2612 signature authorizes the allowance. The API still authenticates the caller and resolves the sender wallet for the queued transaction. User-session requests without valid wallet verification fail before DALP queues the call.

This boundary is narrow. The permit does not move tokens, bypass transfer restrictions, or approve a transfer authority. DALP writes the holder-approved allowance only when the signature, nonce, deadline, and EIP-712 domain pass the permit feature checks.

## Read permit metadata [#read-permit-metadata]

Call `GET /api/v2/tokens/{tokenAddress}/permit-info` before building the EIP-712 message. Pass `owner` when you need the holder's current nonce.

```bash
curl -X GET "$DAPI_URL/api/v2/tokens/0x1111111111111111111111111111111111111111/permit-info?owner=0x2222222222222222222222222222222222222222" \
  -H "X-Api-Key: $DALP_API_TOKEN"
```

When the token has an attached permit feature, the response contains the feature address, EIP-712 domain separator, permit type hash, and the requested holder nonce. DALP reads the domain separator and optional nonce from the live permit feature in one multicall.

```json
{
  "data": {
    "featureAddress": "0x3333333333333333333333333333333333333333",
    "owner": "0x2222222222222222222222222222222222222222",
    "nonce": "7",
    "domainSeparator": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    "permitTypeHash": "0x6e71edae12b1b97f4d1f60370fef10178563ef29188d1232f565f79b8f6aad8c"
  },
  "links": {
    "self": "/v2/tokens/0x1111111111111111111111111111111111111111/permit-info"
  }
}
```

If the token exists but has no attached permit feature, `data` is `null`. If you omit `owner`, DALP still returns the domain fields, but `owner` and `nonce` are `null`. If the token cannot be found in the tenant-scoped index, the API returns a token-not-found error. If the live permit feature cannot return its metadata, the API returns a token-features-unavailable error instead of guessing the domain values.

When you build the EIP-712 typed data, use the returned `featureAddress` as the verifying contract. The permit feature uses the token name, version `1`, the current chain ID, and the permit feature address to build its domain separator.

## Relay a signed permit [#relay-a-signed-permit]

After the holder signs the EIP-2612 message, call `POST /api/v2/tokens/{tokenAddress}/permits` with the signed approval fields.

```bash
curl -X POST "$DAPI_URL/api/v2/tokens/0x1111111111111111111111111111111111111111/permits" \
  -H "X-Api-Key: $DALP_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "owner": "0x2222222222222222222222222222222222222222",
    "spender": "0x4444444444444444444444444444444444444444",
    "value": "1000000000000000000",
    "deadline": "1893456000",
    "v": 27,
    "r": "0x1111111111111111111111111111111111111111111111111111111111111111",
    "s": "0x2222222222222222222222222222222222222222222222222222222222222222"
  }'
```

DALP encodes the feature contract's `permit(owner, spender, value, deadline, v, r, s)` call and submits it through the transaction queue. The caller's selected sender wallet pays for and tracks the queued execution. Synchronous completions return the updated token read-back. Queued completions return transaction tracking data.

## Request fields [#request-fields]

| Field                | Required          | Description                                                                                                              |
| -------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `owner`              | Yes               | Token holder that signed the permit.                                                                                     |
| `spender`            | Yes               | Address approved to spend the holder's tokens.                                                                           |
| `value`              | Yes               | Approved amount in the token's smallest units. The value must fit within `uint256`.                                      |
| `deadline`           | Yes               | Unix timestamp in seconds after which the signature is no longer valid. The value must fit within `uint256`.             |
| `v`                  | Yes               | ECDSA recovery id. DALP accepts `27` or `28`.                                                                            |
| `r`                  | Yes               | ECDSA `r` value as a 32-byte hex string.                                                                                 |
| `s`                  | Yes               | ECDSA `s` value as a 32-byte hex string.                                                                                 |
| `walletVerification` | For user sessions | Wallet verification payload for the sender wallet when the caller uses a user session. API-key requests omit this field. |

## Behaviour and failure cases [#behaviour-and-failure-cases]

* The permit feature must be attached to the token before the mutation can queue a permit call.
* DALP reads permit metadata from the tenant-scoped token index and the live permit feature contract.
* Any authenticated API caller can submit the signature when the relay request is authorized for the sender wallet. User-session requests without valid `walletVerification` are rejected before the transaction is queued. API-key requests use the API key to authenticate the sender.
* The permit call only succeeds when the signed owner, spender, value, nonce, deadline, and domain match the permit feature's checks.
* A successful permit emits the standard ERC-20 `Approval(owner, spender, value)` event. The subsequent token transfer still goes through the token's normal compliance and transfer checks.
* Expired deadlines, stale nonces, wrong domains, malformed signatures, missing permit features, and unavailable live permit metadata fail before the allowance changes.

## Related [#related]

* [Permit token feature](/docs/architects/components/token-features/permit)
* [Token holders and transfers](/docs/developers/api-integration/token-holders-transfers)
* [Token lifecycle API](/docs/developers/api-integration/token-lifecycle)
* [API reference](/docs/developers/api-integration/api-reference)
