DevelopersAccept payments
Shop sales in your integration
How a merchant's shop sales reach your server through the Shop application's webhooks, how to recognise them, and why the API and SDK are unchanged.
A merchant's shop sells through its own application, named "Shop", which the merchant's first shop creates, or the first accepted press of the pay button on one of their open payment links, whichever comes first. Every shop purchase is an ordinary checkout session of that application, so your code sees it the way it sees any session: through webhooks. The shop added no v1 endpoint, no webhook event type and no error code to the API, so the SDK is unchanged.
The Shop application
The Shop application is listed in Developers with the merchant's other applications, but it has no
secret: it cannot be given API keys, renamed or disabled. In the dashboard, a rename, a disable or a
secret roll is refused with HTTP 400 and the code shop_application_locked: "Your shop sells through
this application, so it cannot be renamed, disabled or given API keys. You can still set its webhook
URL." The v1 API never answers this code.
Its webhook URL can be set like any other application's: see Developer settings. It does not count toward the application limit.
What a shop session looks like
| Field | Value |
|---|---|
order_id | shop_ followed by a random UUID, one per click on the shop's button |
| mode | payment for a one-time price, subscription for a recurring one |
metadata | { "source": "shop", "shop_slug": "<the shop's name at purchase time>" } |
success_url | the shop's receipt page, https://<name>.fianto.xyz/thanks/fian_rcpt_… |
cancel_url | the product's page on the shop |
| expiry | 30 minutes |
customer_email | the email the buyer typed on the shop, when they gave one |
A payment-mode order takes the session's metadata, so an order event carries source: shop too.
Receive shop sales
A shop sale sends exactly the events of any checkout session of its mode, to the Shop application's endpoint. Point that endpoint at a route that verifies the signature like any other, and use the metadata when you need to tell shop sales apart:
// app/api/webhooks/fianto-shop/route.ts
import { Webhooks } from '@fianto/nextjs';
export const POST = Webhooks({
secret: process.env.FIANTO_SHOP_WEBHOOK_SECRET!,
onOrderPaid: async (event) => {
if (event.data.metadata?.source === 'shop') {
console.log('shop sale', event.data.metadata.shop_slug, event.data.order_id);
}
},
});Each application has its own webhook endpoint with its own signing secret, so the Shop application's endpoint uses the Shop application's secret.
The merchant's payment links sell through the same application, so once they have links, this
endpoint also receives link payments. Tell them apart by metadata.source (shop or
payment_link), or by the order ID prefix (shop_ or plink_). See
Payment link sales in your integration.
When Fianto suspends a shop
Each checkout of the shop that nobody has started paying is expired at once: you receive
checkout.session.expired, plus order.expired for a one-time purchase. A checkout already being
paid stays open and can still complete. Payment link sessions on the same application are left
alone.
What the API does not show
Every v1 read of orders, payments, checkout sessions, subscriptions and events is scoped to the calling application, and the Shop application can never hold a secret. So no API key can read a shop sale through v1: shop sales reach you only through the Shop application's webhooks and the dashboard. Products and prices are shared by all of a merchant's applications, as before.
See also
Was this page helpful? Tell us
Subscriptions
Sell a recurring USDC price with a subscription session, follow the subscription's status, and cancel it from your server.
Payment link sales in your integration
How payments made through a merchant's payment links reach your server through the Shop application's webhooks, and how to tell them from shop sales.