Documentation Index
Fetch the complete documentation index at: https://glide-9da73dea.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Initiate a payment inside the agent vault envelope. Amounts over the step-up threshold return a pending_step_up response with a URL the user must visit. All on-chain broadcast happens asynchronously via Inngest with a CAS-claim to prevent double-send (PLAN.md F2). on_chain_tx fields on the resulting receipt are server-fetched from RPC, never trusted from the facilitator (PLAN.md F1).
| Field | Value |
|---|
| Name | payments.initiate |
| Category | write |
| Required scope | payments:initiate |
| Idempotency key required | yes |
Annotations
| Annotation | Value |
|---|
| Title | Initiate Payment |
| Read-only | no |
| Destructive | yes |
| Idempotent | yes |
| Open-world | no |
| Requires human approval | yes (step-up) |
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"counterparty": {
"type": "object",
"properties": {
"address": {
"type": "string",
"minLength": 1
},
"chain": {
"type": "string",
"enum": [
"eth",
"base",
"arb",
"op",
"polygon",
"sol"
]
},
"token": {
"type": "string",
"minLength": 1
}
},
"required": [
"address",
"chain",
"token"
],
"additionalProperties": false
},
"amount_cents": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"currency": {
"type": "string",
"minLength": 1,
"maxLength": 8
},
"memo": {
"type": "string",
"maxLength": 280
},
"idempotency_key": {
"type": "string",
"minLength": 8,
"maxLength": 128
},
"mcc": {
"type": "string",
"minLength": 4,
"maxLength": 4
},
"geo": {
"type": "string",
"minLength": 2,
"maxLength": 2
}
},
"required": [
"counterparty",
"amount_cents",
"currency",
"idempotency_key"
],
"additionalProperties": false
}
Output schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"kind": {
"type": "string",
"enum": [
"accepted",
"pending_step_up"
]
},
"pending_payment_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"policy_version": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"risk_verdict": {
"type": "string",
"enum": [
"allow",
"allow_with_step_up"
]
},
"step_up_url": {
"type": "string",
"format": "uri"
},
"enqueued_at": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
}
},
"required": [
"kind",
"pending_payment_id",
"policy_version",
"risk_verdict",
"enqueued_at"
],
"additionalProperties": false
}
Auth
Caller’s grant must include the payments:initiate scope. Grants whose scope set is a superset of the required scope are accepted.
Request examples
curl -X POST https://mcp.glide.co/mcp/write \
-H "Authorization: Bearer $GLIDE_GRANT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "payments.initiate",
"params": {
"counterparty": {
"address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
"chain": "base",
"token": "USDC"
},
"amount_cents": 75000,
"currency": "USD",
"memo": "Invoice #INV-2026-0042 — software license renewal",
"idempotency_key": "inv-2026-0042-payment-attempt-001"
}
}'
Response examples
Success — payment accepted and queued for broadcast:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"kind": "accepted",
"pending_payment_id": "e5f6a7b8-c9d0-1234-efab-345678901234",
"policy_version": 3,
"risk_verdict": "allow",
"enqueued_at": "2026-05-04T12:00:00Z"
}
}
Step-up required (amount exceeds step_up_amount_cents in the envelope):
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32003,
"message": "amount 750000 requires step-up approval",
"data": {
"reason_id": "step_up_required",
"step_up_url": "https://app.glide.co/step-up/e5f6a7b8-c9d0-1234-efab-345678901234?sigil=tok_abc123"
}
}
}
Policy denied — daily cap exceeded:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32002,
"message": "daily spend cap of 100000 cents would be exceeded by this payment",
"data": { "reason_id": "daily_cap_exceeded" }
}
}
Errors
| Code | Name | Cause | Remediation |
|---|
-32600 | Invalid request | Malformed JSON-RPC envelope | Check method, jsonrpc, and id fields |
-32602 | Invalid params | Missing required field, chain not in enum, or idempotency_key too short | Validate against the input schema before calling |
-32001 | Unauthorized | Missing/expired grant token | Refresh via agent.grant.refresh |
-32002 | Policy denied | Amount exceeds per-tx / daily / lifetime cap; counterparty not on allowlist; chain blocked; MCC blocked; geo blocked; sanctions screen hit | Run payments.simulate first to identify the blocking axis |
-32003 | Step-up required | Amount exceeds step_up_amount_cents in the policy envelope | Follow the step-up flow below, then retry with step_up_sigil |
-32004 | Rate limited | Too many initiate calls in a short window | Back off by retry_after_seconds in the error data |
-32005 | Vault contention | Another payment is being broadcast from the same vault | Retry after the in-flight broadcast completes |
-32603 | Internal error | Server-side error during enqueueing | Retry with the same idempotency_key; the call is idempotent |
Step-up flow
When the amount exceeds the step_up_amount_cents threshold in the policy envelope, the server returns a -32003 error with data.step_up_url and data.reason_id: "step_up_required". The payment row is already written in pending state — you do not need to resend the full payload.
import { GlideClient } from './glide-client';
const client = new GlideClient({ grantToken: process.env.GLIDE_GRANT_TOKEN! });
// ── Call 1: initiate ──────────────────────────────────────────────────────
let pendingPaymentId: string;
let stepUpUrl: string | undefined;
try {
const result = await client.call('payments.initiate', {
counterparty: {
address: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
chain: 'base',
token: 'USDC',
},
amount_cents: 750000, // $7,500 — above the step-up threshold
currency: 'USD',
memo: 'Q2 vendor settlement',
idempotency_key: 'q2-vendor-settlement-001',
});
// amount was under step-up threshold — already accepted
pendingPaymentId = result.pending_payment_id;
} catch (err: any) {
if (err.code === -32003) {
// Step-up required — save the pending_payment_id from error context
// and redirect the user to err.data.step_up_url.
stepUpUrl = err.data.step_up_url;
// The pending_payment_id is encoded in the step_up_url path.
// Your UI should open stepUpUrl in a browser or WebView; after the
// user completes biometric, the Glide app posts the sigil back to
// your redirect URI.
console.log('Redirect user to:', stepUpUrl);
// ... wait for the sigil to arrive at your redirect handler ...
} else {
throw err;
}
}
// ── Call 2: retry with sigil (after user completes biometric) ────────────
const stepUpSigil = 'tok_abc123def456'; // received at your redirect URI
const confirmed = await client.call('payments.initiate', {
counterparty: {
address: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
chain: 'base',
token: 'USDC',
},
amount_cents: 750000,
currency: 'USD',
memo: 'Q2 vendor settlement',
idempotency_key: 'q2-vendor-settlement-001', // same key — idempotent
// step_up_sigil is not part of the standard input schema;
// the MCP server reads it from the Authorization header extension.
// Pass it via the client wrapper's sigil option:
});
// result.kind === 'accepted'
console.log('Payment accepted:', confirmed.pending_payment_id);
See Step-up protocol for the full protocol-level reference including sigil expiry, retry semantics, and the redirect URI registration flow.