https://glide.co. Supply your own configured credentials, funded treasury and consented recipients before calling the API. Placeholder UUIDs follow the 11111111-1111-4111-8111-111111111111 shape used throughout the Partner API reference.
What you are building
How the money moves
Three balances, in order. Your treasury USD balance. Glide binds your partner record to one business entity and one entity-scoped USD balance. You prefund it by settling real USD into the bound reserve account, and a Glide operator records that settlement against evidence. There is no deposit API you call. The user’s personal Glide USD balance. A batch payout is a synchronous, atomic book transfer inside Glide: a treasury debit and a user credit, both completed, both zero fee, written in one database transaction. When the call returns 200, the money is spendable. Nothing is queued and nothing is pending. The user sees it as incoming, labelled Payout from partner. The user’s bank. The user, not you, drives the cash-out. They convert USD to USDC inside Glide, review the quoted fees, then continue to a bank withdrawal.Receiving a payout does not require the user to be identity verified. Converting USD on the way to a bank withdrawal does. Payout eligibility also requires an active user, the required consent and a funded, enabled partner treasury. Glide prompts users to verify before conversion and bank payout. Do not build a verification gate in front of your own payouts.
Prerequisites
- A backend you can put a secret in. Every call in this recipe is server-side.
- An HTTPS endpoint on port 443 for webhooks, reachable from the public internet.
- Node 20 or later if you want to run the TypeScript samples, plus
curlandjqfor the shell ones. - Partner credentials from Glide. Step 1 covers how to get them.
1
Get partner credentials from Glide
Ask Glide to create your partner record. You will be asked for:Glide stores only a salted scrypt hash of the secret and can never show it to you again. If you lose it, ask Glide to rotate it. Rotation keeps your
- Your partner name and a URL-safe slug. The name is what users see on the consent screen.
- The exact webhook URLs you want allowlisted. Delivery only goes to an exact match.
- Whether you intend to push payouts, which decides the
treasury:writeentitlement.
client_id and a client_secret once. Client IDs look like gpc_<slug>_<8 hex>, secrets like gps_ followed by 32 random bytes in base64url.client_id and immediately kills the old secret, though tokens already minted stay valid for up to an hour.2
Mint and cache an access token
Glide issues native Send
client_credentials JWTs. There is no authorization server to configure.POST /api/partner/oauth/token with Content-Type: application/x-www-form-urlencoded, a required grant_type=client_credentials, and an optional space-separated scope. Authenticate with HTTP Basic, form-encoding each credential before base64-encoding client_id:client_secret.Authorization: Bearer <access_token> on every other call.Cache it. Tokens last exactly one hour, and issuance is limited to 30 requests a minute per client, counting failed attempts. Minting one per request will rate-limit you under any real load.On a single 401 invalid_token, clear the cache and mint once more. Do not loop. If the second attempt fails too, your credentials or your client status is the problem. Clear the cache on deploy when you rotate the secret.3
Pre-create a user and send the claim link
You bring the email. Glide creates a placeholder account and returns a stable user id plus a link to the consent screen.Store The claim link is navigation to a consent screen, not a bearer capability and not a login bypass. It carries no email and no user id, so it is safe to render in your UI. The person must sign in with the email you pre-created. Glide attaches their verified identity only where the email matches and no identity is attached yet, which preserves the Glide user id, your receipt and any grants. Signing in with a different address consents for that other account instead. If someone uses the wrong address, pre-create the one they actually used and send them that link.Partner placeholders have no account type. The owner picks Individual or Company after claiming, through Glide’s normal one-time selection. You cannot set it and you cannot change it later.
user_id against your own user row. It is stable forever, including after the person claims the account.created describes the first call for your partner and that email. It does not flip on replay, so a repeated call returns the same id and the same created value. If the person already has a Glide account, you get created: false and their existing id. Pre-creation is limited to 60 requests a minute.Glide sends no email. Put claim_link in your own onboarding email or dashboard, and tell the person which address to sign in with.What the user sees
They land on the consent screen, sign in, see your partner name and the exact permissions you asked for, and click Allow access. Approving replaces their scope set for you with exactly what they approved, so a narrower re-consent narrows your access. They can revoke any time under Settings then Integrations.To pay someone you need both
payouts:receive and transfers:read on their grant. The payout writes a transfer the user has to be able to see, so receive consent alone is not enough.4
Read verification, wallets and ledger state
Four reads, each gated by its own consent scope, each limited to 300 requests a minute.Verification status is one of Reading this endpoint never starts provisioning. If the user has no receiving account, they have to complete the deposit-details flow inside Glide.Need the user to verify? Request a hosted link with Results sort by
not_started, in_progress, review, approved or rejected. With no record, it is not_started with null provider and timestamp. You never receive documents, rejection reasons or provider tokens.Wallets come back as an array of evm and solana addresses. An unclaimed user normally has an empty array, so treat empty as “not ready yet” rather than an error.The USD account response is a discriminated union on status. Branch on it before reading account:POST /api/partner/kyc/:id/link, no body, limited to 10 requests a minute. It returns status: "created" with a URL, already_approved with a null URL, or pending with a null URL while the provider is still reviewing. Glide handles the callbacks, so you learn the outcome from kyc.status_changed rather than by polling.Polling the ledger
GET /api/partner/users/:id/transfers returns the user’s personal ledger. Use since as an exclusive lower bound on updated_at, limit between 1 and 100, and follow cursor to the end.updated_at then id, both ascending, at full timestamp precision. Preserve since while paging and only advance your watermark once next_cursor comes back null.amount_cents is an exact string-encoded minor-unit integer, selected as text so JavaScript cannot round it. Parse it as a big integer or a decimal type, never a float. On older rows, status, currency and completed_at can be null.5
Receive and verify webhooks
Ask Glide to allowlist your exact URL and configure the endpoint. Glide returns the signing secret once and keeps only encrypted ciphertext. Each allowlisted URL gets its own secret.Four event types arrive, each gated by the matching consent scope:Each request carries Four rules make this correct:
Content-Type: application/json, Idempotency-Key set to the event id, and X-Glide-Signature: t=<unix-seconds>,v1=<hex HMAC-SHA256>.Verify the HMAC over the exact string ${timestamp}.${rawRequestBody} with a constant-time compare:- Sign over the raw bytes. Capture the body before any JSON middleware touches it.
- Enforce a five minute tolerance. The timestamp and signature are regenerated on each retry while the event id and payload stay identical, so tolerance blocks replay without breaking legitimate retries.
- Dedupe by event id before side effects. Delivery is at least once, and your receiver can accept an event before Glide records the success.
- Return 2xx only after durable acceptance. Network errors, 408, 429 and 5xx are retried. Every other non-2xx, redirects included, is a terminal failure.
6
Pay your users
POST /api/partner/treasury/transfers/batch moves USD from your treasury into 2 to 50 user balances in one atomic transaction.Before the first call, Glide has to have bound your treasury to your business entity and external payer UUID, recorded verified funding, and activated it. That sequence is Go live. Your token needs the treasury:write entitlement, which never appears in user consent.Each recipient needs a pre-creation receipt for your partner, an active account, and both payouts:receive and transfers:read on their grant. There is no verification, wallet or receiving-account gate on this endpoint.The request
SendContent-Type: application/json and a required Idempotency-Key of 1 to 128 characters from [A-Za-z0-9._:-].Amounts and the request total are each capped at
9007199254740991. The streamed body limit is 64 KiB, and the rate limit is 10 requests a minute. The same user may appear twice if each entry is a distinct obligation.Generate execution_id and payout_id once, and persist them next to the obligation before you make the call. They are what makes a lost response recoverable.The response
HTTP 200, including on replay, with one result per item in request order:transfer_id against your payout. It is the correlation key for the ledger read and for transfer.settled. state is always processed, version always 1, fee_cents always "0". total_amount_cents includes reused items, so on a partial replay it can exceed the money this call actually debited.The success audit, batch response, receipts, treasury debit, user credits, activity entry and webhook outbox all commit together. Audit or outbox failure rolls the whole new batch back. You will never receive a successful subset.Retries, exactly
What each error means
Every error body carries a
request_id that matches the X-Request-Id header and the audit row. Log it.Caps
Under the treasury lock Glide enforces per-item, per-batch, rolling 24 hour and lifetime amount caps, plus transfer counts per hour and per 24 hours. Only new transfers consume allowance, so replays are free. Hitting a cap exactly is allowed. Cap errors name the violated limit without revealing remaining allowance.Correlating the webhook
transfer.settled fires from the user’s credit. Match data.transfer_id to the transfer_id you stored from the batch response.7
Let the user cash out
Once the batch returns 200, the money is in the user’s personal Glide USD balance and is spendable. They see it under Glide balance in the Glide app, and the payout appears as incoming, labelled Payout from partner.From there the user drives everything:
- Convert USD to USDC inside Glide, reviewing the quoted fees. This step requires approved verification. Glide explains that on the balance block and links unverified users to identity verification.
- Continue to a bank withdrawal from the conversion receipt, or open the bank flow directly against available USDC.
POST /api/partner/kyc/:id/link and watch for kyc.status_changed with status: "approved".Go-live checklist
Work through Go live for the full ordered sequence. The short version:- Partner created, credentials stored in a secret manager,
treasury:writeenabled, and a native token verified against a read endpoint. - Custody and redemption mandate confirmed, reserve account and settlement evidence identified.
- Business entity created through its normal owner flow, with its real verification status.
- Treasury bound with approved caps and mandate expiry, external funding verified and recorded against its receipt.
- Recipients pre-created, active, and consenting to both
payouts:receiveandtransfers:read. - The exact webhook URL allowlisted, its secret configured, and the receiver validated end to end.
- Proven live in the configured environment: a funded reserve, a small two-recipient batch, the credit visible in each personal USD balance, a signed webhook received and correlated, and a user-authorized bank withdrawal completing.
- Treasury activated only after all of the above, with monitoring on receipts, audits, rolling usage, webhook delivery and reserve reconciliation.
Reading list
- Partner API overview gives the model and every endpoint in one table.
- Authentication covers token claims, scopes, rotation and issuance limits.
- Users and consent covers pre-creation, claiming and how access is checked.
- Payouts is the full treasury contract, including caps and admin operations.
- Webhooks covers signing, retries and consent binding in detail.
- Errors lists every code with its remediation.