Managed Signing
Circle Payment Network (CPN)
3. Permit2 Approval

Step 3: Permit2 Approval (One-Time)

POST
https://api-prod.useknit.io/api/v1/managed-signing/requests
Scopemanaged-signing:writeAuthBearer token

This is a one-time on-chain transaction that approves the Permit2 contract to spend USDC on behalf of your wallet. After this approval, all subsequent CPN V2 payments use gasless EIP-712 signatures.

Prerequisites

  • Wallet must have MATIC (or native token) for gas fees
  • USDC token address for your network
  • Permit2 contract address for your network

Body

{
  "walletId": "<local-wallet-id>",
  "network": "MATIC_MAINNET",
  "type": "evm_tx",
  "kind": "erc20_approve",
  "payload": {
    "token": "<USDC token address>",
    "spender": "<Permit2 contract address>",
    "amount": "<approval amount>"
  },
  "broadcast": true
}
FieldTypeDescription
walletIdstringYour local wallet ID from Step 1
networkstringTarget network (e.g., MATIC_MAINNET)
typestringMust be evm_tx for on-chain transaction
kindstringMust be erc20_approve
payload.tokenstringUSDC contract address
payload.spenderstringPermit2 contract address
payload.amountstringApproval amount (use max for unlimited)
broadcastbooleanSet to true to broadcast on-chain

Approval Amount

  • For unlimited approval: use a large number like 115792089237316195423570985008687907853269984665640564039457584007913129639935 (max uint256)
  • For limited approval: specify the exact amount in token units

Request

curl "https://api-prod.useknit.io/api/v1/managed-signing/requests" \
  -H "Authorization: Bearer $KNIT_ACCESS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "walletId": "<local-wallet-id>",
    "network": "MATIC_MAINNET",
    "type": "evm_tx",
    "kind": "erc20_approve",
    "payload": {
        "token": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
        "spender": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
        "amount": "115792089237316195423570985008687907853269984665640564039457584007913129639935"
    },
    "broadcast": true
}'

Response

Response
{
  "statusCode": 201,
  "message": "Signing request created",
  "data": {
    "id": "<local-request-id>",
    "businessId": "<business-id>",
    "walletId": "<local-wallet-id>",
    "network": "MATIC_MAINNET",
    "type": "evm_tx",
    "kind": "erc20_approve",
    "status": "SIGNED",
    "payload": {
      "token": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
      "spender": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
      "amount": "115792089237316195423570985008687907853269984665640564039457584007913129639935"
    },
    "txHash": "0x...",
    "broadcast": true,
    "createdAt": "2026-01-20T18:30:40.912Z",
    "updatedAt": "2026-01-20T18:30:40.912Z"
  },
  "success": true
}

Important Notes

  • This transaction requires gas paid by the wallet
  • The service will auto-fill gas/fees/nonce if an RPC is configured for the network
  • If broadcast is false, you'll receive the signed transaction to broadcast yourself
  • This approval only needs to be done once per token

Next Step

Proceed to Per-Payment Signature to sign individual payments.