Managed permits
Sign an EIP-2612 permit with a holder's managed key, store it as a pending signed permit, list stored permits, and relay one later as the token custodian.
Managed permits let the platform sign an EIP-2612 approval with a holder's managed key, store it, and relay it on-chain later as the token custodian. Use this flow when the holder's key is managed by DALP and you want to prepare an approval now and submit it on-chain when it is needed.
This is a different flow from relaying an externally signed permit. If a holder signs the EIP-2612 message in their own wallet, relay it directly with Token permits. Use managed permits when DALP holds the signing key and the platform signs on the holder's behalf.
The flow has three steps:
- Sign and store a permit over the holder's own balance. No transaction is sent yet.
- List stored permits to see which one can be relayed next.
- Relay a stored permit on-chain as the token custodian.
For permit metadata and the EIP-712 domain, see Token permits. For the feature model, see Permit architecture.
Prerequisites
- The token has the
permitfeature attached. It attaches without operator input on almost every template. - The signing step runs against the caller's own managed token-holding wallet. The permit owner is always the authenticated caller's wallet; it is never read from the request body, so a caller cannot sign over another holder's balance.
- The relay step requires the token's
custodianrole. The custodian's sender wallet pays for the relay transaction. - User-session calls that sign or relay need a configured wallet-verification method, such as PIN code, secret code, or one-time password, and must include the matching
walletVerificationpayload. API-key sessions skip wallet verification.
Step 1: Sign and store a permit
Sign an EIP-2612 permit over the caller's own balance and store it as a pending signed permit. This call signs the permit with the holder's managed key and saves it; it does not send a transaction.
curl -X POST "$DAPI_URL/api/v2/tokens/0xTOKEN/features/permit/signatures" \
--header "X-Api-Key: $DALP_API_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"spender": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
"value": "1000000000000000000",
"deadline": "1767225600"
}'The body carries only the approval terms:
| Field | Meaning |
|---|---|
spender | The address being approved to spend the holder's tokens. |
value | Approved amount in the token's smallest units, as a uint256 decimal string. Use the uint256 maximum for an unlimited approval, or 0 to revoke. |
deadline | Signature deadline as a Unix timestamp in seconds. |
There is no owner field. The permit owner is resolved server-side from the authenticated caller's wallet.
The response returns the stored permit:
{
"data": {
"id": "018f9b2a-7c3e-7a10-9c1b-2f5e8d4a6b71",
"tokenAddress": "0xTOKEN",
"owner": "0x1111111111111111111111111111111111111111",
"spender": "0x71c7656ec7ab88b098defb751b7401b5f6d8976f",
"value": "1000000000000000000",
"deadline": "1767225600",
"nonce": "0",
"signatureKind": "ecdsa",
"status": "pending",
"createdAt": "2026-06-12T08:00:00.000Z"
},
"links": {
"self": "/v2/tokens/0xTOKEN/features/permit/signatures/018f9b2a-7c3e-7a10-9c1b-2f5e8d4a6b71"
}
}Keep the id. You pass it to the relay step. A freshly signed permit always starts as pending.
| Field | Meaning |
|---|---|
nonce | EIP-2612 permit nonce assigned at signing time. Stored permits relay in nonce order. |
signatureKind | ecdsa for an externally owned account holder, bytes for a smart-wallet holder verified on-chain via EIP-1271. |
status | Persistence status. A freshly signed permit is always pending. |
Step 2: List stored permits
List the token's stored permits to see which one can be relayed next. The list is scoped to your organization.
curl --globoff -X GET "$DAPI_URL/api/v2/tokens/0xTOKEN/features/permit/signatures?filter[status]=pending" \
--header "X-Api-Key: $DALP_API_TOKEN"Each row reports a computed display status and whether it can be relayed right now:
| Field | Meaning |
|---|---|
status | relayed once relayed on-chain, expired when the deadline passed or the nonce was superseded by the owner's current on-chain nonce, otherwise pending. |
relayable | true only when the permit is pending, its nonce equals the owner's current on-chain nonce, and its deadline has not passed. |
relayedTxHash | Transaction hash of the relay, or null while the permit is unrelayed. |
The list sorts by nonce ascending by default, which is relay order: the smallest unrelayed nonce relays first. Filter to one holder with ?filter[owner]=0xHOLDER, or to a status with ?filter[status]=pending. Relay the row whose relayable is true.
Step 3: Relay a stored permit
Relay a stored permit on-chain by passing its id as signedPermitId. This step requires the token's custodian role and submits the approval on the holder's behalf.
curl -X POST "$DAPI_URL/api/v2/tokens/0xTOKEN/features/permit/permits" \
--header "X-Api-Key: $DALP_API_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"signedPermitId": "018f9b2a-7c3e-7a10-9c1b-2f5e8d4a6b71"
}'DALP loads the stored signature, checks that the permit is still relayable against the holder's live on-chain nonce, and submits it through the transaction queue. The relay returns either a synchronous completion or a queued (202) response, depending on the request mode and how the queue resolves.
When the relay settles on-chain, the stored permit's status becomes relayed and relayedTxHash is populated. The relay response itself returns the token state and transaction metadata, not the stored permit row, so read the final permit status from the list endpoint rather than the relay response. Poll the returned status URL to confirm the relay transaction reached its terminal state, then re-read the permit through GET /api/v2/tokens/{tokenAddress}/features/permit/signatures to see its relayed status and relayedTxHash.
A permit only sets an allowance. Any later transfer still runs through the token's normal compliance and transfer checks.
The same endpoint also relays an externally signed permit when you send the raw signature fields instead of signedPermitId. See Token permits for that form.
Endpoints
| Endpoint | Use it for |
|---|---|
POST /api/v2/tokens/{tokenAddress}/features/permit/signatures | Sign a permit over the caller's own balance and store it as pending. |
GET /api/v2/tokens/{tokenAddress}/features/permit/signatures | List stored permits with computed status and relayability. |
POST /api/v2/tokens/{tokenAddress}/features/permit/permits | Relay a stored permit by signedPermitId, or an externally signed permit by raw fields. |
Troubleshooting
| What you see | What to check |
|---|---|
| Relay rejected: stored permit not found | Confirm the signedPermitId is correct and belongs to your organization. See DALP-0662. |
| Relay rejected: already relayed | A relayed permit cannot be relayed again. Sign a fresh permit. See DALP-0663. |
| Relay rejected: expired or out of order | Relay pending permits in nonce order, and sign a new permit if the deadline has passed. See DALP-0664. |
For the full error list, see the Platform API error reference.
Read next
- Token permits for relaying an externally signed permit and inspecting permit replay history.
- permit feature API reference for the EIP-712 domain and signing payload.
- Permit architecture
Token permits
Read EIP-2612 permit metadata, relay signed permit approvals, and inspect permit replay history for DALP asset tokens.
Token conversion records
Read indexed conversion lifecycle records for a DALP token, including replay identifiers, status, converted amounts, and target-side issuance details.