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.

3 min read

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

FieldValue
order_idshop_ followed by a random UUID, one per click on the shop's button
modepayment for a one-time price, subscription for a recurring one
metadata{ "source": "shop", "shop_slug": "<the shop's name at purchase time>" }
success_urlthe shop's receipt page, https://<name>.fianto.xyz/thanks/fian_rcpt_…
cancel_urlthe product's page on the shop
expiry30 minutes
customer_emailthe 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

On this page