---
title: "Allocate a grant and return the EIP-712 payload the owner signs"
method: POST
path: "/wallets/{address}/policies:prepare"
tags: ["Policies"]
---

# Allocate a grant and return the EIP-712 payload the owner signs

`POST /wallets/{address}/policies:prepare`

Allocates the policy id, validation entity, and session signer, builds
the exact `installValidation` calldata the signature will commit to,
and returns the typed data for `eth_signTypedData_v4`. Stores nothing:
a prepare that is never submitted leaves no state behind. The echoed
fields must be passed back verbatim to `:submit` — the gateway
recomputes everything from them, so tampering only produces a
signature that no longer verifies.

## Request body

- PreparePolicyRequest
  - `chainId` integer, required — Numeric chain ID (e.g. 11155111 for Sepolia, 8453 for Base). On chain-aware trigger/node configs this is required and must be a configured chain; on query/filter params it is optional.
  - `agentLabel` string, required
  - `justification` string
  - `allowedActions` AllowedAction[], required
    - `target` string, required — Lowercase or checksummed hex EOA / contract address.
    - `selectors` string[], required — 4-byte function selectors permitted on the target.
  - `erc20SpendCap` Erc20SpendCap, required — Cumulative ERC-20 spend cap, enforced on-chain at execution. The token must appear as an `allowedActions` target.
    - `token` string, required — Lowercase or checksummed hex EOA / contract address.
    - `amount` string, required — Total cap in the token's smallest unit (decimal string, no reset).
  - `expiresInSeconds` integer, required — Grant lifetime, relative (skew-proof). Becomes an absolute validUntil.

## Response `200`

Payload to sign, plus the allocations submit must echo.

- PreparedPolicy
  - `policyId` string, required — ULID identifier (26-char Crockford base32).
  - `chainId` integer, required — Numeric chain ID (e.g. 11155111 for Sepolia, 8453 for Base). On chain-aware trigger/node configs this is required and must be a configured chain; on query/filter params it is optional.
  - `entityId` integer, required — The validation entity allocated for this grant (provisional until submit).
  - `sessionSigner` string, required — Lowercase or checksummed hex EOA / contract address.
  - `deadline` integer, required — Unix seconds; bounds signing → first use, NOT the grant lifetime.
  - `validUntil` integer, required — Absolute grant expiry, unix milliseconds. Echo verbatim to submit.
  - `digest` string, required — The EIP-712 hash the typed data produces, for client-side verification.
  - `typedData` object, required — The exact eth_signTypedData_v4 payload for the owner's wallet.

## Other responses

- `400` — Request validation failed.
- `401` — Missing or invalid bearer token.
- `403` — Authenticated but not permitted.
- `404` — Resource not found.

---

[API](https://skmtc.net/avaprotocol/apis/ava-protocol-avs-api.md) · [All operations](https://skmtc.net/avaprotocol/apis/ava-protocol-avs-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/avaprotocol/ava-protocol-avs-api/versions/231d563f2c9f/schema)
