Managed Signing
Circle Payment Network (CPN)
4. Per-Payment Signature

Knit API Documentation

Step 4: Per-Payment Signature (CPN V2)

Endpoint

POST

{{baseUrl}}/api/v1/managed-signing/requests

For each CPN V2 payment, Circle provides a messageToBeSigned (EIP-712 typed data). You sign it using this endpoint and return the signature to Circle.

How CPN V2 Works
1. Initiate payment with Circle → Circle returns `messageToBeSigned`
2. Sign with Knit API          → Knit returns `signature`
3. Submit to Circle            → Circle processes the payment
Headers
  • X-API-KEY: Your API key for authentication.
  • Accept: Set to application/json to receive responses in JSON format.
  • Content-Type: Set to application/json.
Request Body
{
  "walletId": "<local-wallet-id>",
  "network": "MATIC_MAINNET",
  "type": "eip712",
  "payload": {
    "typedData": {
      "primaryType": "PermitWitnessTransferFrom",
      "domain": {
        "name": "Permit2",
        "chainId": 137,
        "verifyingContract": "0x000000000022D473030F116dDEE9F6B43aC78BA3"
      },
      "types": {
        "PermitWitnessTransferFrom": [
          { "name": "permitted", "type": "TokenPermissions" },
          { "name": "spender", "type": "address" },
          { "name": "nonce", "type": "uint256" },
          { "name": "deadline", "type": "uint256" },
          { "name": "witness", "type": "..." }
        ],
        "TokenPermissions": [
          { "name": "token", "type": "address" },
          { "name": "amount", "type": "uint256" }
        ]
      },
      "message": {
        "permitted": {
          "token": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
          "amount": "1000000"
        },
        "spender": "0x...",
        "nonce": "...",
        "deadline": "...",
        "witness": "..."
      }
    }
  }
}
FieldTypeDescription
walletIdstringYour local wallet ID
networkstringTarget network
typestringMust be eip712 for typed data signing
payload.typedDataobjectCircle's messageToBeSigned (EIP-712 format)
Important

The typedData object should be exactly as provided by Circle's API. Do not modify or camelCase the keys in types or message - they must match the EIP-712 schema exactly.

Sample Request
curl --location -g '{{baseUrl}}/api/v1/managed-signing/requests' \
--header 'X-API-KEY: {{apiKey}}' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{
    "walletId": "<local-wallet-id>",
    "network": "MATIC_MAINNET",
    "type": "eip712",
    "payload": {
        "typedData": { "...Circle messageToBeSigned..." }
    }
}'
Sample Response
Sample Response
{
  "statusCode": 201,
  "message": "Signing request created",
  "data": {
    "id": "<local-request-id>",
    "businessId": "<business-id>",
    "walletId": "<local-wallet-id>",
    "network": "MATIC_MAINNET",
    "type": "eip712",
    "status": "SIGNED",
    "payload": {
      "typedData": { "..." }
    },
    "signature": "0x...",
    "createdAt": "2026-01-20T18:30:40.912Z",
    "updatedAt": "2026-01-20T18:30:40.912Z"
  },
  "success": true
}
Using the Signature

Take the signature from the response and include it in Circle's payment submission step:

{
  "signature": "0x..."
}
Gasless Signing

Unlike the Permit2 approval step, EIP-712 signing is completely gasless. The signature is generated off-chain and no blockchain transaction is required.

Error Handling
ErrorCauseSolution
POLICY_DENIEDtypedData not allowed by policyEnsure typedData.allow: true in your policy
INVALID_TYPED_DATAMalformed EIP-712 dataVerify the typedData matches Circle's format exactly
Integration Example
// 1. Initiate payment with Circle
const circleResponse = await circle.initiatePayment({
  amount: "10.00",
  currency: "USD"
});
 
// 2. Sign with Knit
const knitResponse = await fetch('{{baseUrl}}/api/v1/managed-signing/requests', {
  method: 'POST',
  headers: {
    'X-API-KEY': apiKey,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    walletId: walletId,
    network: 'MATIC_MAINNET',
    type: 'eip712',
    payload: {
      typedData: circleResponse.messageToBeSigned
    }
  })
});
 
const { signature } = (await knitResponse.json()).data;
 
// 3. Submit to Circle
await circle.submitPayment({
  paymentId: circleResponse.paymentId,
  signature: signature
});

Contact

business@useknit.io

Knit Business Financial Services Ltd.
3080 Yonge St
Toronto ON, M4N 3N1, Canada

Subscribe to our newsletter

A monthly digest of the latest news, articles, and resources.

Knit logo

© KNIT BUSINESS FINANCIAL SERVICES LIMITED is duly registered by the Financial Transactions and Reports Analysis Centre of Canada (FINTRAC) as a Money Service Business (C100000256)