Claude
Skills
Sign in
Back

inflow-payments

Included with Lifetime
$97 forever

Integrate InFlow stablecoin payments into any project. Use this skill when the user wants to: accept payments, add a checkout, request a payment, build a payment flow, integrate InFlow, accept USDC/USDT/EURC/PYUSD, set up consumer login via InFlow, register users with InFlow, handle payment webhooks, create spending policies for autonomous agents, build a 0-click headless payment flow, or add InFlow checkout to a marketplace app (note: native multi-recipient splits are not supported by the InFlow API). Also trigger on: 'add inflow', 'inflow payment', 'inflow checkout', 'stablecoin payment', 'crypto payment', 'accept stablecoins', 'pay with usdc', 'inflow webhook', 'inflow login', 'inflow policy'.

Backend & APIs

What this skill does


# InFlow Payments Integration

InFlow is a stablecoin payment platform. Sellers (merchants, agents) request payments from consumers; consumers approve via mobile/email/SMS; settlements happen on-chain. Consumers can pre-configure **policies** that auto-approve requests within budget — enabling 0-click flows for autonomous agents.

This skill integrates InFlow into any project — backend service, full-stack web app, CLI, autonomous agent, or worker — without forcing a specific framework or language. **Important:** the integration itself is always backend work. Browser code is only ever the optional `inflow.js` popup (UX only); every REST call to InFlow and the `INFLOW_API_KEY` live exclusively on the server. See the Hard Backend Gate section for the rule and how to handle projects without a backend yet.

## What InFlow Supports

| Capability | Endpoint(s) | Use case |
|---|---|---|
| **User search** | `POST /v1/users/search` | Find a consumer by email, mobile, or username |
| **User registration** | `POST /v1/requests/register` | Onboard a new consumer (out-of-band approval) |
| **Login** | `POST /v1/requests/login` | Authenticate a consumer (out-of-band approval) |
| **Payment** | `POST /v1/requests/payment` | Request a stablecoin payment from a consumer |
| **Policies** | `POST /v1/policies`, `POST /v1/requests/policy` | Pre-approved spending rules for headless / 0-click flows |
| **Webhooks** | Inbound `POST` to your endpoint | Receive transaction/approval status changes |
| **Polling fallback** | `GET /v1/requests/{requestId}` | Check status without webhooks |
| **Wallet read** | `GET /v1/balances`, `GET /v1/transactions` | Read balances and transaction history |
| **Crypto wallets** | `GET/POST /v1/deposit-addresses`, `/v1/withdrawal-addresses` | Manage on-chain wallet addresses |
| **Agentic users** | `POST /v1/users/agentic` | Create a programmatic account, get an API key |

**Currencies:** `USDC`, `USDT`, `EURC`, `PYUSD` (stablecoins only — no fiat)
**Blockchains:** `APTOS`, `BASE`, `SOLANA`, `WORLD`

## What This Skill Does NOT Do

These features are **not exposed by the InFlow public API**. If the user asks for any of them, stop and tell them they're not supported — do not attempt workarounds:

- **Marketplace splits** — No `splits[]` field on `PaymentRequest`. Multi-recipient payments would need separate sequential requests with no atomic guarantee.
- **Refund creation** — Transactions can have status `REFUNDED`, but there's no API to initiate one. Refunds are dashboard-only or out-of-band.
- **Webhook URL registration via API** — Webhook URLs are configured via the InFlow dashboard. There's no `POST /v1/webhooks` to register them programmatically.
- **OAuth flow for sellers** — Despite some legacy documentation referencing "OAuth", consumer authentication is entirely SDK-mediated. There's no OAuth dance for the integrating seller.

---

## Defaults & Decision Tree

When the user doesn't specify, use these defaults:

| Question | Default | Why |
|---|---|---|
| Currency | `USDC` | Most widely-held stablecoin |
| `userDetails` field | `["EMAIL"]` | Required field; email is the minimum useful identifier |
| Display mode | See decision below | Depends on whether a browser is involved |
| Production vs sandbox | Sandbox SDK URL until user confirms | Production SDK URL is not yet documented |

**Display mode:** `FULL` if the consumer is interacting with a browser at the moment of payment (and the page can load `inflow.js`). `HEADLESS` for everything else: server-to-server, autonomous agents, scheduled jobs, AI workers.

**Webhook vs polling:** Webhooks for production. Polling only for local development, scripts, or anything without a public HTTPS endpoint.

**User identification:** A payment must be addressed to a known `userId`. The agent must either:
- Get the `userId` from the user (if they already know it), OR
- Search by email/mobile/username via `POST /v1/users/search`, OR
- Register a new consumer if the search returns 404

Always do user identification BEFORE creating a payment request.

---

## 🛑 Hard Backend Gate (Read Before ANY Code)

InFlow integration is **always backend work**. The `INFLOW_API_KEY` is a merchant key that must never reach a browser. There is no exception, demo mode, or "just for now" carve-out.

### Mandatory gate

Before writing any InFlow HTTP call, you MUST be able to **name the single server-only surface** where `X-API-Key` will be set. Acceptable surfaces:

- An Express / Fastify / Koa / Hono / Hapi route handler
- A Next.js Route Handler (`app/api/.../route.ts`) or Server Action — NOT a Client Component
- A SvelteKit `+server.ts` / `+page.server.ts` — NOT a `+page.svelte` component
- A Nuxt `server/api/*.ts` / `server/routes/*.ts` — NOT a Vue component or composable
- A Remix `loader` / `action` — NOT a route component body
- A serverless function: Vercel Function, Netlify Function, Cloudflare Worker, AWS Lambda, etc.
- A Python / Go / Rust / .NET / Java HTTP service
- A standalone backend script or worker (no browser involved)

If the project does NOT have any such surface — for example, a pure Vite + React SPA, a static site, a Storybook setup, a Chrome extension popup — **STOP**. Tell the user they need a backend surface for the API key, even if it's a single-file serverless function or a 30-line Express server. Offer to scaffold one. Do not proceed until the user agrees and the backend surface exists.

### Framework-specific footguns (key-leak mechanics)

These are real, common ways merchant keys end up in browsers. Refuse them all.

**Next.js:**
- `process.env.INFLOW_API_KEY` referenced inside a `'use client'` component is `undefined` at runtime — Next.js does NOT bundle non-`NEXT_PUBLIC_` env vars into client code. The bug surfaces as a broken request with no auth header.
- The disaster happens when an agent "fixes" this `undefined` by renaming the var to `NEXT_PUBLIC_INFLOW_API_KEY`. That prefix tells the bundler to inline the value into the client bundle → **the key is now shipped to every visitor**.
- **NEVER prefix `INFLOW_API_KEY` with `NEXT_PUBLIC_`.** The correct fix is to move the call to a Server Component, Route Handler (`app/api/.../route.ts`), or Server Action — never to make the key public.

**Vite (React, Vue, Svelte, Solid, etc.):**
- `import.meta.env.INFLOW_API_KEY` is `undefined` unless prefixed with `VITE_`. Some agents "fix" this by renaming to `VITE_INFLOW_API_KEY` → **Vite then inlines the key into the client bundle and ships it to every visitor**.
- **NEVER prefix `INFLOW_API_KEY` with `VITE_`.** Vite has no server runtime by itself. If you need a backend, the user has to add one (Express, Fastify, or pair with a serverless function).

**SvelteKit:**
- Components and `+page.svelte` files run in the browser. Use `+server.ts`, `+page.server.ts`, or `$lib/server/*` (the `server` directory is enforced as server-only by the bundler).

**Nuxt:**
- Vue components and composables run in the browser. Use `server/api/*` route handlers or `server/utils/*`. Never read `INFLOW_API_KEY` from a `<script setup>` block in a `.vue` file.

**Astro / Remix / Qwik / Solid Start:**
- All have a server/client split. The rule is the same: `INFLOW_API_KEY` is read only inside the framework's server boundary (loader, action, server route, etc.), never in component code.

### The "just a demo" trap

If the user says *"this is just a demo"*, *"just for testing"*, *"we'll add the backend later"*, *"just for now"*, or anything similar — **the rule still applies**. Embedded merchant keys leak via:

- Git history (especially after a `git push --force` "fix")
- Browser devtools (anyone can open them)
- Browser extensions (they read your scripts)
- Error reports / crash dumps shared in tickets
- Screenshots posted in Slack / GitHub / Stack Overflow
- Build artifacts uploaded to CDNs
- Deployed preview URLs that get crawled

A "temporary" key in the browser is a permanent key on the internet. There is no safe sho
Files: 4
Size: 60.6 KB
Complexity: 52/100
Category: Backend & APIs

Related in Backend & APIs