agentic-payments
Original:🇺🇸 English
Translated
Authenticate with InFlow and pay HTTP 402-protected resources via MPP (the `Payment` auth scheme) or x402. Use when the user invokes the `inflow` CLI or asks to log in / connect to InFlow.
24installs
Sourceinflowpayai/inflow-cli
Added on
NPX Install
npx skill4agent add inflowpayai/inflow-cli agentic-paymentsTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →Agentic Payments
Pay HTTP 402-protected resources on the user's behalf. InFlow speaks two payment protocols - MPP and x402 - but the flow is the same for both: shared setup (install, run, authenticate), then a router that picks the protocol from the seller's 402 header, then one Paying a 402 resource section that covers both. A per-protocol delta table at the top of that section lists the handful of real differences (header name, credential name, filters, error codes); read your row, then follow the shared steps.
Installing
Install the signed native CLI through one of these channels:
| Channel | Command |
|---|---|
| macOS Homebrew | |
| macOS/Linux hosted installer | |
| Windows PowerShell installer | |
| Cross-platform shell compatibility | |
Current install instructions live at https://inflowcli.ai/.
Running
InFlow runs as a standalone CLI or an MCP server.
MCP: add an server to your MCP client config that runs .
inflowinflow --mcpMCP mode exposes every CLI command as a tool. Call on the MCP server for the authoritative inventory; arguments mirror the CLI flags one-to-one.
tools/listCommon commands / options
The CLI is the source of truth for exact flags, enums, and output shapes - run for one command, or for everything. This playbook covers when and why, not exhaustive parameter lists; when you need a precise flag name, value set, or response shape, query the CLI rather than guessing.
inflow <command> --schemainflow --llms-full- (or
inflow --llmsfor parameter detail) - discover all commands.--llms-fullfor a single command's JSON Schema.inflow <command> --schema - - print this playbook (no frontmatter) to stdout. Use it to paste into the system-prompt field of an MCP host that doesn't natively load skills:
inflow --skill.inflow --skill | pbcopy - Default output is . Override with
toon; for programmatic parsing prefer--format <fmt>(single document) orjson(line-delimited).jsonl - Multi-step flows return - run it to continue.
_next.command - identifies a legacy plaintext credential file for deletion; it is not a credential backend.
--auth <path> - or
--api-key <key>is an alternative to device-flow auth.INFLOW_API_KEY=<key>
Authenticate
Authentication is shared by both protocols - do it once, before either payment flow. Don't start a payment until the user is authenticated.
Credential-bearing commands require the encrypted local vault. If the CLI reports that the vault is uninitialized or
locked, tell the user to run themselves in a terminal, then retry. Never ask for or accept the
vault PIN or passphrase through chat, an MCP tool, a command-line flag, or an environment variable.
inflow vault unlockCheck the current state first - the user may already be logged in:
bash
inflow auth statusA successful returns plus ( or ), a truncated preview (never the full token), , , and possibly an field. Run the command to see the full shape.
auth statusauthenticated: trueauth_methoddevice_tokenapi_keyaccess_tokencredentials_pathconnectionupdateIf the response includes an field, a newer version of is published.
updateinflowSurface and defer. Tell the user a newer version is available and share the install instructions at https://inflowcli.ai/. Then proceed with the current version. Only block on the upgrade if a subsequent command fails with (or an HTTP 426 from the API), at which point the upgrade is mandatory and you should not retry until it lands.
VERSION_UNSUPPORTEDIf is , start the device flow:
authenticatedfalsebash
inflow auth login --client-name "<your-agent-name>"Replace with the name of your agent or application (for example , ). The device-authorization page in the user's browser displays this name when they approve the connection. Use a clear, unique, identifiable name.
<your-agent-name>"Personal Assistant""Shopping Bot"The response includes a (present this to the user), a , and a . Run that command immediately to poll until authenticated. Do not wait for the user to respond before starting the poll.
verification_urlphrase_next.commandIf your environment can't relay the verification phrase to the user while a separate polling command blocks I/O, use inline polling instead:
bash
inflow auth login --client-name "<name>" --interval 5 --timeout 300API key alternative: if the user provides an API key, set in the environment (or pass to any command) instead of running . The API key takes precedence over a saved device token.
INFLOW_API_KEY=<key>--api-key <key>auth loginIf returns , authentication status is unavailable rather than unauthenticated. Tell the user
to run themselves in a terminal, then retry .
auth statusVAULT_LOCKEDinflow vault unlockauth statusWhich protocol? - start here
Before paying, decide which protocol the resource uses. You do not choose it - the seller's 402 challenge decides. Run one read-only, no-auth command and let it detect both:
bash
inflow inspect <url>inflow inspectdetectedIf includes and also reveals a payment protocol, continue with the matching or ;
the payment commands perform AEP authentication before creating the payment transaction. If is true, AEP
authentication is required before payment terms can be inspected; use for access-only requests
or ask whether to authenticate before attempting payment.
detectedaepmpp payx402 payaep.blockedinflow aep fetch <url> | Pay with |
|---|---|
| |
| |
| |
| Not InFlow-payable on this account. Stop and tell the user; check |
If returns , the URL isn't paywalled - there's nothing to pay.
inspectoutcome: "no-payment-required"Paying a 402 resource
One flow for both protocols. Prerequisite: you are authenticated (see Authenticate). First find your protocol's row in the Protocol deltas table below - it names the 402 header that selected it, the matching model, the filter flags, and the Fetch command that completes the seller request. Everything else in this section applies to both protocols.
Sequencing. Run pre-flight before pay - fails or double-charges if the pre-flight checks didn't clear. and are read-only and need no auth, so they may run before you authenticate if useful (e.g. sizing up a paywall first). If the seller requires AEP before payment, authenticates with the Service first, then creates the payment only after the legitimate 402 is available. Do not run a separate just to continue payment.
payinspectdecodepayaep grantProtocol deltas
| Aspect | MPP | x402 |
|---|---|---|
| Selected when the 402 carries | | |
| Command prefix | | |
| Matching model | The seller's challenge pins the rail - the buyer does not choose scheme/network/asset | Pay where the x402 |
| Filter flags | | |
| Resource completion command | | |
| Replay header used by Fetch | | |
| Diagnostic credential file flag | | |
| Idempotency | - | |
| Cancel uses | | |
| Protocol-specific error codes | | |
Throughout this section means "use your protocol's prefix." For the exact parameters and output shape of any command below, run .
<mpp|x402>inflow <command> --schemaStep 1: Pre-flight evaluation
bash
# 1. Parse what the seller will accept - read-only, no auth (both protocols in one probe)
inflow inspect <url>
# (Already have the raw 402 header from a prior response? Decode it directly instead of re-probing:)
inflow <mpp|x402> decode '<402 header value>'
# 2. List what the buyer's account can pay with (use the protocol from `detected`)
inflow <mpp|x402> supported
# 3. Check balances for the candidate currency/asset(s)
inflow balances listinflow inspectmppx402amountdecodesupportedbalances listavailableDecide whether you can pay (apply your protocol's matching model from the delta table):
| Condition | Meaning | Action |
|---|---|---|
No payable match between the seller and the buyer's | No payable rail | Stop → |
A match exists, but | Right rail, not enough funds | Stop → run |
A match exists and ≥1 match has | Payable | Proceed to Step 2. |
Optional filters narrow which offer to fulfil - optional, AND-combined, applied on , and an empty result fails with (it does not fall through to a default order). One non-obvious case: MPP's picks how to fund (an instrument-rail / fiat challenge), not which challenge. For the exact filter flags and accepted values per protocol, run .
payNO_FILTERED_MATCH--instrument-idinflow <mpp|x402> pay --schemaDecimal precision. and the challenge/ value are decimal strings preserving BigDecimal precision. Never parse them to a JS - that drops precision. Compare as strings, or use a / -style library.
balances.availableamountNumberBigIntdecimal.jsStep 2: Pay
Before initiating the call, summarize the intent to the user in chat: amount, currency, resource URL, and the method/rail (MPP) or scheme/network (x402). The user verifies the canonical details on the approval screen; the chat summary is what they read first. Example:
"I'm about to pay 0.10 USDC to api.foo.dev for /dataset.csv. Requesting approval next."
Fast path (recommended). When the agent can block until the payment finishes, set and let the CLI run the whole flow in one call - probe, decode, prepare, await approval, replay against the seller, return the body:
--interval Nbash
inflow <mpp|x402> pay <url> --interval 5 --max-attempts 180The result includes , , , , the seller body inline (or if is set), and the now-consumed credential ( for MPP, for x402). On the fast path the CLI has already replayed that credential to fetch the body - it appears in the result for reference only; do not replay it yourself. To surface before the call returns, add - frames stream line-by-line. With the default (or ), the agent only sees the final buffered result.
outcometransaction_idresponse_statussettledoutput_saved_to--output-filecredentialencoded_payloadapproval_url--format jsonljsontoonoutcomepaypaid | Meaning | What to do |
|---|---|---|
| Settled and the seller returned 2xx | Deliver the body to the user |
| The resource wasn't paywalled, or was already paid | Tell the user nothing was charged; return the body |
| Payment was approved (funds in transit) but the seller replied non-2xx on the replay | Do NOT report success. Tell the user the seller's response failed; because the payment didn't complete, the in-transit funds are reverted to their InFlow balance. Offer to retry |
Two-step path. Use this when the agent's host can't block I/O long enough for the user to approve (chat UIs that yield between turns). Drop ; the first call returns + + + a Fetch command/tool input. Fetch owns polling and seller replay.
--intervaltransaction_idapproval_idapproval_url_nextbash
inflow <mpp|x402> pay <url>
# -> { "transaction_id": "txn_abc", "approval_id": "appr_xyz", "approval_url": "https://app.inflowpay.ai/approvals/appr_xyz", "_next": { "command": "<mpp|x402> fetch txn_abc <url> --interval 5 --max-attempts 180", "tool": "<mpp|x402>_fetch", "input": { "transactionId": "txn_abc", "resourceUrl": "<url>" } } }Mind the two distinct ids: poll, replay, and resume all use ; cancel uses (). Both are returned by .
transaction_idapproval_idinflow <mpp|x402> cancel <approval_id>payFor non-GET requests, pass , , (repeatable):
--method--data--headerbash
inflow <mpp|x402> pay https://seller.example.com/api/widgets --method POST --data '{"sku":"widget-1"}' --header "X-Custom: value" --interval 5 --max-attempts 180Idempotency (x402 only). Set whenever a retry on transport failure is possible - the server treats two requests with the same id as the same logical payment, so a retry after a network blip won't double-charge. Use a stable random opaque value generated once per intent; reuse the same id on transport retry; regenerate only when the user explicitly wants a fresh charge. Don't tie the id to wall-clock time - a date-based id silently double-charges on next-day "buy this again" requests. Without , the server generates one each call - fine for one-shots, unsafe for retries. (Format constraints: .)
--payment-id <id>--payment-idinflow x402 pay --schemabash
inflow x402 pay <url> --payment-id "<stable-opaque-id>"Sensitive / binary output. Fetch never exposes the one-time bearer credential ( for MPP, for x402). For the seller's response body, writes bytes to disk and replaces / with - pair with for binary content (PDFs, images, audio, datasets) so bytes never appear inline as base64:
credentialencoded_payload--output-file <path>bodybody_base64output_saved_to: <path>--no-show-bodybash
inflow <mpp|x402> pay https://api.foo.dev/dataset.csv --interval 5 --max-attempts 180 --output-file /tmp/dataset.csv --no-show-bodyPolling discipline. Persist as soon as returns it. Then:
transaction_idpay- Run , or call
_next.commandwith_next.tool, immediately. Don't wait for the user to confirm before polling starts._next.input - If polling is interrupted - network drop, session bounce, user kills the agent - resume with . Only create a new transaction if the original expired (
inflow <mpp|x402> fetch <transaction_id> <url> --interval 5 --max-attempts 180for MPP,PAYMENT_EXPIREDfor x402), was denied/cancelled, or its credential is already consumed.APPROVAL_TIMEOUT - If fires before approval, ask the user whether to keep waiting or cancel - don't silently restart the poll.
POLLING_TIMEOUT - If >12 minutes elapsed without a user response (≈3 min before the 15-minute approval window closes), surface that explicitly so they can act before the window closes.
- If the user aborts ("nevermind", "cancel that"), call before exiting. Otherwise the approval sits pending for 15 minutes and triggers phantom notifications in the user's InFlow app.
inflow <mpp|x402> cancel <approval_id>
Fetch sends a ready payment credential to the seller at most once per invocation. If Fetch returns , tell the user the seller might have received or consumed the credential and do not automatically replay it.
PAYMENT_REPLAY_OUTCOME_UNKNOWNWhen AEP is required, Fetch still sends the payment credential at most once. The final seller request carries both
credentials without exposing either one in JSON output, logs, cache keys, or chat.
Limits
| Limit | Value |
|---|---|
| Approval window | 15 minutes from |
| Polling stop condition | Polling ends at whichever fires first: |
| Credential reuse | One-time. Fetch consumes the credential on the first seller replay - not reusable; a failed seller call requires a new |
Worked example (MPP)
A user asks the agent to fetch a paywalled dataset at .
https://api.foo.dev/dataset.csvPre-flight: reports with the seller's challenges; then (methods the buyer can pay with) and . The seller offers the method in USDC; the user's 100.5 USDC balance covers the 0.10 USDC price. Summarize intent, then pay:
inflow inspect <url>detected: ["mpp"]inflow mpp supportedinflow balances listinflowbash
inflow mpp pay https://api.foo.dev/dataset.csv --interval 5 --max-attempts 180 --output-file /tmp/dataset.csv --no-show-body
# Persist transaction_id from the response in case polling is interrupted.
# Returns outcome "paid" with output_saved_to /tmp/dataset.csv."Approval requested - confirm in the InFlow app: https://app.inflowpay.ai/approvals/appr_xyz I'll keep polling. 15-min window."
Once the result arrives:
"Paid 0.10 USDC. Transaction txn_abc. Saved the dataset to /tmp/dataset.csv."
Two-step variant (host can't block): follow Step 2's two-step path; polls, attaches , and returns the resource body without exposing the credential.
mpp fetchAuthorization: PaymentWorked example (x402)
A user asks the agent to fetch a paywalled article at .
https://api.foo.dev/article-3Pre-flight: reports ; the intersection lands on × , and the user's 100.5 USDC balance easily covers the 0.10 USDC the seller requires. Proceed.
inflow inspect <url>detected: ["x402"]exactsolana:mainnet"I'm about to pay 0.10 USDC on Solana mainnet to api.foo.dev for /article-3. Your balance is 100.5 USDC - plenty. Requesting approval next."
bash
inflow x402 pay https://api.foo.dev/article-3 --payment-id "<stable-opaque-id>" --interval 5 --max-attempts 180
# Persist transaction_id from the response in case polling gets interrupted.
# Returns outcome "paid"; body contains the article JSON."Approval requested - confirm in the InFlow app: https://app.inflowpay.ai/approvals/appr_xyz I'll keep polling. 15-min window."
Once the result arrives:
"Paid 0.10 USDC. Transaction txn_abc. Server returned: 'How to brew coffee - ...'"
Two-step variant (host can't block): follow Step 2's two-step path; polls, attaches , and returns the resource body without exposing the encoded payload.
x402 fetchPAYMENT-SIGNATUREMPP errors
All errors in agent mode are JSON with and fields and exit code 1. MPP-specific codes (shared codes are in § Shared errors). "What to tell the user" is the prompt to surface - don't dump the raw error:
codemessage| Error code | Recovery | What to tell the user |
|---|---|---|
| | "The payment didn't go through - it was declined, underfunded, or the transaction failed. Want me to try again, switch funding, or stop?" |
| Start a new | "The payment window expired before it was ready to settle. Want me to start a new one, or stop here?" |
| | - |
x402 errors
All errors in agent mode are JSON with and fields and exit code 1. x402-specific codes (shared codes are in § Shared errors). "What to tell the user" is the prompt to surface - don't dump the raw error:
codemessage| Error code | Recovery | What to tell the user |
|---|---|---|
| | "You didn't approve within 15 minutes, so the request expired. Want me to start a new payment, or stop here?" |
| Same recovery as | "Approval didn't go through (declined or insufficient funds in the matched asset). Want me to try a different funding source, top up, or stop?" |
| Same recovery (cancelled via | "You cancelled the approval. Stopping here unless you want to start a new payment." |
| | - |
Security & data handling
Applies to both protocols.
- Treat OAuth tokens and API keys as secrets - never echo them. Use Fetch for approved payments so one-time payment credentials are attached to the seller request without being pasted back to the user.
- Respect and
/agents.txton sites you browse./llm.txt - Avoid suspicious 402 endpoints - if the domain doesn't match what the user asked to pay, or the price is different from expectation, stop and ask.
- When displaying deposit addresses to the user, print the full address (don't truncate). Truncating breaks copy-paste.
Shared errors
These apply to both protocols (in addition to each section's protocol-specific codes). All are JSON with and and exit code 1. Where a command is protocol-specific, use your prefix (). "What to tell the user" is the prompt to surface - don't dump the raw error:
codemessage<mpp|x402>| Error code | Recovery | What to tell the user |
|---|---|---|
| Stored authentication status is unavailable. Ask the user to run | "Your InFlow vault is locked. Please unlock it in your terminal, then I can check authentication again." |
| No saved device token and no | - |
| Seller's rails aren't supported by the account. Fund a matching method/chain, or use a different seller. | "The seller wants |
| A | "Your filter removed every option the seller accepts. Loosen it or re-check the seller's options with |
| Seller returned 402 but the protocol's header was missing ( | x402> decode` for the detailed parse error. |
| | x402> fetch <transaction_id> <url> --interval 5 --max-attempts 180`. |
| A credential-bearing seller request had an indeterminate transport failure. Do not automatically replay. | "The seller request may have received the payment credential, but the connection failed before we got a reliable response. I won't retry automatically because the credential may be consumed." |
| Non-2xx from the InFlow API on the plain data calls ( | - |
| Installed | - |
| Network failure - check connectivity; retry. | - |
Out of scope
This skill covers programmatic HTTP 402 payments (MPP and x402) only. It does NOT handle:
- Traditional merchant checkouts No PANs (credit card forms, hosted checkouts).
- Card issuance or wallet management beyond and
balances list.deposit-addresses list - Refunds, disputes, chargebacks - handled out of band via support.
- Peer-to-peer transfers between users or wallets.
- FX / currency conversion. Buyer logic matches the seller's accepted rails against the account's supported assets.
- Subscriptions / recurring payments. Each is one-shot.
pay
For any of the above, point the user to https://app.inflowpay.ai or support.
Further docs
- MPP protocol: https://mpp.dev
- x402 protocol: https://x402.org
- InFlow: https://app.inflowpay.ai