Managed Signing
Create Signing Request

Create Signing Request

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

This endpoint creates a new signing request. Supports EVM transactions, EIP-712 typed data signing, and EIP-191 message signing.

Signing Request Types

TypeDescription
evm_txEVM transaction signing (e.g., ERC20 approvals, ERC20 transfers, raw transactions)
eip712EIP-712 typed data signing (structured data with domain separator)
eip191EIP-191 message signing (personal sign messages)

Supported Networks

Production

  • ETHEREUM_MAINNET
  • MATIC_MAINNET
  • BSC_MAINNET
  • BASE_MAINNET

Testnet (Sandbox/Dev only)

  • MATIC_AMOY - Polygon Amoy testnet

Body

FieldTypeRequiredDescription
walletIdstringYesLocal wallet ID
networkstringYesTarget network
typestringYesRequest type (evm_tx, eip712, or eip191)
kindstringConditionalTransaction kind (required for evm_tx: erc20_approve, erc20_transfer, or raw)
payloadobjectYesRequest payload
broadcastbooleanNoWhether to broadcast the transaction
idempotencyKeystringNoIdempotency key for request deduplication

EVM Transaction (ERC20 Approve)

{
  "walletId": "<local-wallet-id>",
  "network": "MATIC_MAINNET",
  "type": "evm_tx",
  "kind": "erc20_approve",
  "payload": {
    "token": "0xToken",
    "spender": "0xSpender",
    "amount": "10"
  },
  "broadcast": false,
  "idempotencyKey": "optional-idem-key"
}

Payload Fields for ERC20 Approve

FieldTypeDescription
tokenstringToken contract address
spenderstringSpender address
amountstringApproval amount (in base units)

EVM Transaction (ERC20 Transfer)

{
  "walletId": "<local-wallet-id>",
  "network": "ETH_MAINNET",
  "type": "evm_tx",
  "kind": "erc20_transfer",
  "broadcast": true,
  "payload": {
    "token": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
    "to": "0x1111111111111111111111111111111111111111",
    "amount": "1000000"
  }
}

Payload Fields for ERC20 Transfer

FieldTypeDescription
tokenstringERC20 token contract address
tostringRecipient address
amountstringTransfer amount in base units (e.g., 1000000 for 1.0 USDC)
txOverridesobject(Optional) Gas overrides (e.g., gasLimit)

Note: The broadcast field is commonly set to true for transfers so the signed transaction is submitted on-chain. When broadcast: true, the response includes a txHash. When broadcast: false, the response includes rawSignedTx for manual submission.

Transfer requests are subject to policy rules including tokens, rateLimits, requireApprovalAbove, and maxTransferAmount.


EIP-712 Typed Data

{
  "walletId": "<local-wallet-id>",
  "network": "ETHEREUM_MAINNET",
  "type": "eip712",
  "payload": {
    "typedData": {
      "primaryType": "Permit",
      "domain": {
        "name": "USD Coin",
        "version": "2",
        "chainId": 1,
        "verifyingContract": "0xToken"
      },
      "types": {
        "Permit": [
          { "name": "owner", "type": "address" }
        ]
      },
      "message": {
        "owner": "0xOwner",
        "spender": "0xSpender"
      }
    }
  }
}

Important: typedData.types and typedData.message keys must match the EIP-712 schema exactly and should not be camelCased.

Payload Fields for EIP-712

FieldTypeDescription
typedDataobjectEIP-712 typed data structure
typedData.primaryTypestringPrimary type name
typedData.domainobjectDomain separator fields
typedData.typesobjectType definitions
typedData.messageobjectMessage to sign

EIP-191 Message Signing

{
  "walletId": "<local-wallet-id>",
  "network": "ETHEREUM_MAINNET",
  "type": "eip191",
  "payload": {
    "message": "Sign this message to verify ownership"
  }
}

Payload Fields for EIP-191

FieldTypeDescription
messagestringThe message to sign

EIP-191 is commonly used for:

  • Wallet ownership verification
  • Off-chain authentication
  • Simple message signing without structured data

Sample Request (EVM TX)

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": "0xToken",
        "spender": "0xSpender",
        "amount": "10"
    },
    "broadcast": false
}'

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": "AWAITING_APPROVAL",
    "payload": {
      "token": "0xToken",
      "spender": "0xSpender",
      "amount": "10"
    },
    "broadcast": false,
    "createdAt": "2026-01-20T18:30:40.912Z",
    "updatedAt": "2026-01-20T18:30:40.912Z"
  },
  "success": true
}

Response Fields

FieldTypeDescription
idstringLocal request ID (use this in subsequent requests)
businessIdstringYour business ID
walletIdstringLocal wallet ID
networkstringTarget network
typestringRequest type
kindstringTransaction kind
statusstringRequest status
payloadobjectRequest payload
broadcastbooleanBroadcast flag
signaturestringThe cryptographic signature (when signed)
rawSignedTxstringFull signed transaction (if broadcast: false)
txHashstringTransaction hash (if broadcast: true)
decisionTraceobjectPolicy evaluation details
errorMessagestringError details (if status is FAILED or POLICY_DENIED)
createdAtstringCreation timestamp
updatedAtstringLast update timestamp

Request Statuses

StatusDescription
AWAITING_APPROVALRequest is pending manual approval (exceeds policy threshold)
SIGNEDRequest was signed successfully
POLICY_DENIEDRequest was denied by policy rules
FAILEDRequest failed (see errorMessage for details)