Skip to main content

Launch Payment for Stripe from your app (URL schemes)

Short answer: Your app or website opens a payment:// URL, Payment for Stripe takes the payment, then opens your callback URL with the result. No SDK. No server work. It works the same on iPhone and Android, with a few differences called out below.

The full reference lives at paymentforstripe.com/api.

How it works

  1. Your app opens a payment:// URL with parameters.
  2. Payment for Stripe opens and sets up the sale. The merchant takes the payment with a reader, Tap to Pay, or a typed card.
  3. When it's done, the app opens your callback URL with the result added as query parameters.

The merchant needs to be signed in. If a link arrives while another charge is running, the app turns it down and your callback gets error=charge_in_progress.

Create a charge: payment://new

A one-time payment for an amount you set.

Name Type Required Description
amount integer Yes Amount in the currency's smallest unit, greater than 0. 1000 = $10.00.
currency string No Three-letter ISO code, like usd or eur. Leave it out and the app uses the currency it's already set to.
description string No Charge description. URL-encode it.
customer string No Existing Stripe customer ID (cus_…). customer_id works too. When set, email and name are ignored.
email string No Customer email. Creates a new customer.
name string No Customer name. URL-encode it. Creates a new customer.
metadata string No URL-encoded JSON object of key-value pairs, added to the payment. Stripe's metadata limits apply.
callback string No URL to open when the sale finishes.
autoprocess boolean No true skips the keypad and starts the charge right away. Default false.
auto_return boolean No true opens the callback as soon as the result is known. Default false: the callback waits until the merchant closes the result screen.
payment://new?amount=2500&currency=eur&description=Coffee%20and%20pastry
payment://new?amount=3500&autoprocess=true&auto_return=true&callback=myapp://payment-complete

A link with a missing, zero, or non-numeric amount is ignored.

Create an invoice from your catalog: payment://cart

Fills the cart with prices from your Stripe product catalog. The merchant then charges as usual, and the sale is saved in Stripe as a paid invoice with those line items. It doesn't email an invoice to your customer.

Name Type Required Description
prices string Yes Comma-separated price_id:quantity pairs, like price_abc:2,price_xyz:1. line_items works too.
coupon string No Stripe coupon ID to apply to the cart.
customer string No Existing Stripe customer ID. customer_id works too.
email string No Customer email. Creates a new customer.
name string No Customer name. URL-encode it.
metadata string No URL-encoded JSON object of key-value pairs.
callback string No URL to open when the sale finishes.
autoprocess boolean No true starts the charge once every price (and the coupon) has loaded.
auto_return boolean No Same as above. Default false.
payment://cart?prices=price_coffee:2,price_muffin:1&email=customer@example.com

Don't send amount with prices. The total comes from the prices, and a link with both is ignored. Prices hidden with payment_hidden still work here.

Pay an existing invoice: payment://invoice

Collects an in-person payment for an open Stripe invoice. The amount, currency, customer, and tax all come from the invoice. On success, the app marks the invoice paid. Works on iPhone and Android.

Name Type Required Description
id string Yes Stripe invoice ID. Must start with in_. Send an open invoice. On iPhone, a draft is finalized first. On Android, a draft is turned down with error=invoice_state_changed.
metadata string No URL-encoded JSON object, added to the PaymentIntent.
callback string No URL to open when the sale finishes. Gets invoice_id and payment_intent_id on success.
autoprocess boolean No true starts the charge after the invoice checks pass, only when a card reader is connected.
auto_return boolean No Same as above. Default false.
payment://invoice?id=in_1ABC123xyz&autoprocess=true&callback=myapp://invoice-paid

The invoice sets the sale, so any of amount, currency, customer, customer_id, email, name, description, coupon, prices, or line_items gets the link turned down with error=invoice_invalid_param. Invoices that are paid, void, uncollectible, $0, tied to a subscription, or set to charge a default payment method are turned down too, each with its own invoice_… error.

The callback

The app adds these to your callback URL:

Name Type Sent Description
status string Always success, error, or cancelled.
charge_id string On success The payment's ID. On iPhone it's the Stripe charge (ch_…). On Android it's the PaymentIntent (pi_…).
stripe_charge_id string Android only The Stripe charge (ch_…).
payment_intent_id string On success The PaymentIntent. iPhone sends it for payment://invoice only. Android sends it for every card payment.
invoice_id string Invoice links The paid invoice, for payment://invoice.
amount integer On success Amount charged, in the smallest unit.
currency string On success Lowercase ISO code.
error string On error A short code like charge_in_progress or invoice_already_paid, or a readable message for a declined card.
myapp://payment-complete?status=success&charge_id=ch_3Qx…&success=true&amount=3500&currency=usd&chargeId=ch_3Qx…

Need the same ID on both platforms? Read stripe_charge_id first, then fall back to charge_id.

For older integrations, the app also sends success=true, chargeId, cancelled=true, and error[message]. New code should read status.

A cancel opens the callback right away. A charge's success or error waits for the merchant to close the result screen, unless you pass auto_return=true. On iPhone, a cash sale never opens the callback, since nothing was charged.

URL encoding

  • Encode every value that has spaces or symbols. Spaces become %20, { and } become %7B and %7D, " becomes %22, : becomes %3A.
  • If your callback URL has its own query string, encode the whole callback so its & doesn't split your payment:// link.
  • The commas and colons in prices can stay as they are.

Metadata {"order_id":"1234","location":"Store A"} becomes:

payment://new?amount=10000&description=Invoice%20%231234&metadata=%7B%22order_id%22%3A%221234%22%2C%22location%22%3A%22Store%20A%22%7D

The older metadata[order_id]=1234 form works too.

Was this article helpful?
0 out of 0 found this helpful