SDKs

Rust

Use the InFlow Rust SDK to accept payments in your service or make paid requests from your application. Choose the crates for MPP, x402, or both, and run them on your application’s Tokio runtime.

GitHub repository. The table below links each payment package on crates.io and its API reference on docs.rs.

Install the crates you need

Use Rust 1.93 or later. A crate is a Rust package: select the buyer crates when your application makes payments, the seller crates when it accepts payments, or both when it performs both roles.

Crate and API referenceUse it to
inflow-mpp-buyer · APIPrepare MPP credentials and wait for approval. Your application sends the credential to the seller.
inflow-mpp-seller · APICreate signed offers and accept payments before delivering a resource.
inflow-x402-buyer · APIPrepare x402 payments or make paid requests through its HTTP helper.
inflow-x402-seller · APIBuild offers and use InFlow’s facilitator for verification and settlement.
inflow-x402-axum · APIProtect specific Axum routes with x402 payment middleware.

For the buyer snippets on this page, add these dependencies from your application’s Cargo directory:

cargo add inflow-mpp-buyer@0.4.1 inflow-x402-buyer@0.4.1
cargo add reqwest@0.13 --no-default-features --features rustls
cargo add tokio@1 --features macros,rt-multi-thread

For the seller examples, use the MPP seller crate or the x402 seller and Axum crates. The example applications also use Axum and JSON serialization:

cargo add inflow-mpp-seller@0.4.1 inflow-mpp@0.4.1
cargo add inflow-x402-seller@0.4.1 inflow-x402-axum@0.4.1
cargo add axum@0.8 serde_json@1
cargo add tokio@1 --features macros,rt-multi-thread,net

Install only the protocols you need. Cargo names use hyphens, while Rust imports use underscores, such as inflow_mpp_buyer. Shared types are re-exported by the role-specific crates. Add inflow-mpp directly when using its additional codecs, including receipt decoding. The optional x402 evm and solana features are for external wallets, not required for InFlow-managed payments.

Configure your application

Accepting payments requires an InFlow Seller account. A buyer can use a Developer or Seller account. Create the matching environment’s API key as described in Accounts and environments.

use inflow_mpp_buyer::{Authentication, ClientOptions, Environment};

pub fn sandbox_options() -> Result<ClientOptions, std::env::VarError> {
    Ok(ClientOptions {
        environment: Environment::Sandbox,
        authentication: Authentication::ApiKey(std::env::var("INFLOW_API_KEY")?),
        ..Default::default()
    })
}

Your application reads INFLOW_API_KEY; the SDK does not load it automatically. Set the environment explicitly because the default is production. These configuration types are also re-exported by the other buyer and seller crates, so import them from the crate you use. Keep the API key on the InFlow client, not in headers sent to a seller’s resource URL.

The MPP buyer constructor makes no network calls. The x402 buyer constructor loads supported payment capabilities, and seller constructors load configuration asynchronously. Complete those startup calls before accepting traffic. Use your application’s Tokio runtime; the SDK does not start another runtime.

An MPP seller also needs a private challenge-signing secret of at least 32 bytes. It is separate from the API key. Store a stable secret and share it across service instances that accept the same challenges; replacing it invalidates outstanding challenges.

Accept payments in a Rust service

Keep your paid operation in your application’s handler. Configure its price and payment options from your service’s settings, then use the appropriate seller integration to check payment before returning the result.

  • For MPP, construct Seller and an Offer. An unpaid request receives the offer’s signed challenge. On the paid request, decode the credential and call Offer::accept against those expected terms. It validates and settles before returning a receipt. Only then run the paid operation and return the receipt with the resource. The MPP seller example shows this in an Axum handler; the SDK operations can be used with other HTTP frameworks.
  • For x402, construct Seller, build a route with Seller::route, and pass it to payment_layer from inflow-x402-axum. Apply the layer to the specific paid Axum route. The x402 seller example verifies payment, runs the handler, and settles before releasing its successful response. The lower-level seller crate does not require Axum.

These integrations do not replace your service’s authentication. For an authenticated MPP route, enforce login or credentials separately and set requires_auth: true so payment uses Payment-Authorization rather than occupying Authorization.

Rust supports buying MPP subscriptions, but its MPP seller integration supports charge payments only. For handler side effects and failed settlement, read Understand verification and settlement and Deliver paid results.

Make paid requests

MPP: prepare a credential, then send it

Your HTTP client first requests the resource. If it receives HTTP 402, collect the WWW-Authenticate values and parse them with parse_challenges. Inspect the offered method, currency and amount, and select the challenge you intend to pay. For an InFlow charge, this function obtains a credential for that selected challenge; it does not send a request to the seller.

use inflow_mpp_buyer::{
    Buyer, CancellationToken, ClientOptions, Credential, Error, PaymentChallenge, PaymentOptions,
    WaitOptions,
};

pub async fn prepare_mpp(
    options: ClientOptions,
    challenge: &PaymentChallenge,
    cancellation: &CancellationToken,
) -> Result<Credential, Error> {
    let buyer = Buyer::new(options)?;
    let payment = buyer
        .prepare(challenge, PaymentOptions::default(), cancellation)
        .await?;
    payment.wait(WaitOptions::default()).await
}

Send the complete credential with encode_credential, prefixed by Payment . Use the header named by credential.challenge.header, or Authorization when it is absent. Preserve separate service authentication, disable redirects, and send the credential only to the intended resource. The complete MPP buyer includes request parsing, offer selection, credential encoding and receipt inspection.

x402: use the HTTP helper

HttpBuyer::execute sends the initial request and, when needed, one paid retry. It returns a free response without creating a payment. The helper refuses redirects and requires a replayable request body before sending the request or creating a payment. Build a reqwest::Request with your target URL and pass it to this function; HttpBuyer owns the HTTP client that sends it.

use inflow_x402_buyer::{
    Buyer, BuyerOptions, CancellationToken, ClientOptions, Error, HttpBuyer, SignOptions,
    WaitOptions,
};

pub async fn fetch_x402(
    options: ClientOptions,
    request: reqwest::Request,
    cancellation: &CancellationToken,
) -> Result<reqwest::Response, Error> {
    let buyer = Buyer::new(
        BuyerOptions {
            client: options,
            ..Default::default()
        },
        cancellation,
    )
    .await?;
    let payments = HttpBuyer::new(Some(buyer))?;
    payments
        .execute(
            request,
            SignOptions::default(),
            WaitOptions::default(),
            cancellation,
        )
        .await
}

This uses the default InFlow-managed preference: balance, then exact. Call it only for a destination you intend to pay. Choose payment options explains selection controls; External wallets covers applications that supply their own signer.

The function returns the response so your application can check its status, receipt and body. A second 402 or a failed delivery is not permission to create another payment. The complete x402 buyer demonstrates those checks. A credential permits a paid request; it is not a settlement receipt or proof that the resource was delivered.

Manage approvals and cancellation

Both buyers expose a prepared payment before waiting. Retain its transaction and approval identifiers when your application needs to display progress or investigate a failure. The MPP helper above goes straight from preparation to waiting; adapt it to display those identifiers when needed. x402 also provides Buyer::prepare for applications that manage the steps explicitly.

  • Request and approval timeouts are different. ClientOptions defaults to 30 seconds per platform request. WaitOptions defaults to a 15-minute approval wait with five-second polling. The x402 HTTP helper separately limits merchant requests to 30 seconds. Give an owner enough time to respond; an approval wait is not an ordinary short HTTP request.
  • A payment’s wait consumes its handle. Capture the identifiers and a cancellation token before waiting if you need them elsewhere. Explicitly awaiting cancel on a prepared payment waits for the known approval’s cancellation attempt. Failed or cancelled waits also attempt cleanup, with an independent five-second limit.
  • Dropping a pending handle or wait future schedules best-effort cleanup. The Tokio runtime must stay alive for that work to finish. Do not treat dropping a value as confirmation that the remote approval was cancelled. If creation failed before returning an approval identifier, the SDK cannot cancel an unknown approval. Cancellation never refunds a completed payment.

InFlow errors expose code, http_status, endpoint and request_id when available. Preserve useful identifiers, not keys or payment credentials. HTTP resource errors and application failures need their own handling. Use Status and recovery after an uncertain result rather than starting another purchase.

Run a Sandbox example

Clone the Rust repository to run its complete examples. The sellers run locally, but configuration, approval and payment use InFlow Sandbox. The example application package is not published; use the SDK crates, not inflow-examples, as dependencies in your own application.

git clone --branch v0.4.1 https://github.com/inflowpayai/inflow-rust.git
cd inflow-rust
cargo build --locked -p inflow-examples --bins

In the first terminal, set your Seller account’s Sandbox API key, generate a signing secret for this local run, and start the MPP seller:

export INFLOW_API_KEY='YOUR_SANDBOX_SELLER_API_KEY'
export MPP_SECRET_KEY="$(openssl rand -hex 32)"
cargo run --locked -p inflow-examples --bin mpp-seller

It listens on port 3000. An unpaid request to /api/widgets receives a 402 challenge for 0.01 USDC. The /free route returns HTTP 200 without payment. Keep a stable signing secret when deploying a real service.

Fund the buyer’s Sandbox balance with at least 0.01 USDC before continuing. Open Sandbox Deposit, select USDC and a network, and send test tokens to the displayed address. Networks and currencies lists the faucets. Wait for the funds to appear in Sandbox Balances.

In a second terminal in the cloned repository, set the buyer’s key and run:

export INFLOW_API_KEY='YOUR_SANDBOX_BUYER_API_KEY'
cargo run --locked -p inflow-examples --bin mpp-buyer

The buyer prints the selected charge and approval identifier. Approve in the Sandbox dashboard if requested. Success prints HTTP 200, the widgets response and the seller receipt. Check the payment in the dashboard too. The example selects the first InFlow charge; it is not an interactive price-confirmation interface.

To test x402 instead, run this command in the Seller-key terminal:

cargo run --locked -p inflow-examples --bin x402-seller

Then run this command in the buyer-key terminal:

cargo run --locked -p inflow-examples --bin x402-buyer

The x402 seller uses port 3001 and does not need the MPP signing secret. Both pairs of examples read exported environment variables, not .env files. Press Ctrl-C to cancel a pending buyer; the examples keep the runtime alive for bounded approval cleanup. Stop and investigate an uncertain payment result before rerunning a buyer.

The Rust examples guide also provides a payment-status command that reads an existing transaction without making another purchase. For additional features, see Subscriptions, External wallets and Trusted agent verification. Trusted-agent verification uses the independent inflow-tap-seller crate and does not require an InFlow account.

Continue your integration

Accept a payment

Protect an endpoint and confirm its first paid response.

Make a payment

Complete a purchase with the intended account and payment option.