Call the Spendkit MCP API
This page shows the actual HTTP requests a client sends. Your application can be written in any language that supports OAuth Client Credentials, JSON-RPC over HTTP, and an EVM wallet signer. Spendkit exposes payment tools through MCP; it does not expose a separate public REST payment API.
Want to start with a complete JavaScript, Python, Go, or C++ file? Copy an example →
In the dashboard, create an Agent, bind and verify its Payment Wallet, set an onchain Spending Policy, and select Connect Agent. Save that connection's Client ID and Client Secret in your server or Runtime secret store. Use read-only access while building the first calls; authorization requires Full Runtime Access. Dashboard setup →
1. Exchange connection credentials for a token
Send a form-encoded OAuth 2.0 Client Credentials request. Both HTTP Basic and form-body credentials are supported. The example uses form fields. Omit scope to request the scopes assigned to the connection; any explicit scope must be a subset of those scopes.
curl -sS -X POST 'https://spendkit-alpha.vercel.app/oauth/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'client_id=<client-id>' \
--data-urlencode 'client_secret=<client-secret>'
Response shape:
{
"access_token": "ska_...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "policy:read payment:preview payment:authorize payment:read payment:record"
}
Scopes in the response depend on the connection. Cache the token until shortly before expiry, then request another one. Keep the Client Secret out of browser code, model prompts, logs, and Git.
2. Discover the MCP server and tools
Put the returned access token in your Runtime's SPENDKIT_ACCESS_TOKEN variable for the examples below. Send JSON-RPC 2.0 to POST /mcp with that Bearer token. The current preferred protocol is 2026-07-28: start with server/discover, then tools/list. In a real program, let an MCP client manage the envelope. The headers and params._meta below show what a direct HTTP implementation must send.
curl -sS -X POST 'https://spendkit-alpha.vercel.app/mcp' \
-H "Authorization: Bearer $SPENDKIT_ACCESS_TOKEN" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'MCP-Protocol-Version: 2026-07-28' \
-H 'Mcp-Method: server/discover' \
--data '{"jsonrpc":"2.0","id":1,"method":"server/discover","params":{"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientInfo":{"name":"my-agent","version":"1.0.0"},"io.modelcontextprotocol/clientCapabilities":{}}}}'
For tools/list, send the same request with Mcp-Method: tools/list and "method":"tools/list". Its result.tools array contains the current names, descriptions, annotations, and JSON input schemas. Do not hard-code an old schema when discovery is available. Older compatible clients can use the supported 2025-11-25 initialize flow.
curl -sS -X POST 'https://spendkit-alpha.vercel.app/mcp' \
-H "Authorization: Bearer $SPENDKIT_ACCESS_TOKEN" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'MCP-Protocol-Version: 2026-07-28' \
-H 'Mcp-Method: tools/list' \
--data '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientInfo":{"name":"my-agent","version":"1.0.0"},"io.modelcontextprotocol/clientCapabilities":{}}}}'
3. Call a tool and read its result
Use tools/call. Modern MCP also requires Mcp-Method: tools/call and a Mcp-Name header matching params.name. This example is read-only and does not issue an authorization:
POST /mcp
Authorization: Bearer <access-token>
Content-Type: application/json
Accept: application/json
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: spendkit_preview_payment
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "spendkit_preview_payment",
"arguments": {
"amount": "0.01",
"recipient": "0x1111111111111111111111111111111111111111",
"token": "USDG"
},
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": { "name": "my-agent", "version": "1.0.0" },
"io.modelcontextprotocol/clientCapabilities": {}
}
}
}
Example response structure, showing selected fields only:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"resultType": "complete",
"structuredContent": {
"allowed": true,
"reason": "policy_allows_payment",
"amount": "0.01",
"token": "USDG"
},
"content": [{ "type": "text", "text": "{...}" }]
}
}
The actual structuredContent also includes Policy and wallet details plus spendkit.traceId; the text content contains the JSON form. Parse result.structuredContent when your client supports it. Check result.isError and structuredContent.allowed or accepted as appropriate. HTTP 200 alone does not mean Spendkit allowed a payment.
4. Complete a real payment in your Runtime
- Call
spendkit_get_connectionandspendkit_get_policywith{}. Match the returned Agent, network, bound wallet, and active Policy to your Runtime configuration. - Call
spendkit_preview_paymentwith{"amount":"0.01","recipient":"0x...","token":"USDG"}. Stop on DENY. - Call
spendkit_authorize_paymentfor the same payment, adding a stableidempotencyKeyfor this one logical payment. A successful response containsintentId,authorization, andtransaction. - In trusted wallet code, compare the authorization and transaction with the requested amount and recipient, the bound wallet, the current chain, and the Router from
get_connection. Submit exactly the returnedtransaction.to,transaction.data, andtransaction.valuefromtransaction.from. The Payment Wallet pays gas; Spendkit Server does not broadcast. - After wallet submission, call
spendkit_record_paymentwithintentIdand the actualtxHash. Callspendkit_get_payment_statusuntil the status is settled. An authorization or submitted transaction is not confirmation.
If a broadcast outcome is uncertain, query the existing intent and chain transaction before any retry. Never blindly submit the same payment again. The local reference client shows OAuth refresh, MCP transport, wallet checks, and payment orchestration.