Review & publishing

First publication is reviewed by a person. After that, code behind your URL ships freely — what waits for approval is anything that changes what your app is permitted to do or how it presents itself. This section is the whole contract: what review checks, what gets an app rejected, and what gets one removed.

Submitting

Shell
paysio apps check                          # the reviewer's checklist, locally; exit 1 on failure
paysio apps deploy --url https://my-app.example.com
paysio apps submit --changelog "What changed in this version"
paysio apps versions                       # where each version stands

apps check runs exactly what review runs first, so a rejection is never a surprise. It fails on:

  • No app URL, an http URL, or one pointing at localhost or a tunnel.
  • No scopes declared, or a scope that does not exist.
  • Missing tagline, description, support email or privacy policy URL (https).
  • An empty changelog on the version.

What a person checks

Review mirrors the App Guidelines one to one. A reviewer:

  1. Reads the listing and confirms it describes what the app does and for whom, without describing a scope as something other than what it is.
  2. Looks at the scope set and asks whether each one is needed for the described function.
  3. Opens the app in a sandbox workspace and exercises it: install, the first screen, the main flow, a popup, a mode switch, uninstall.
  4. Checks the frame headers, that the app is https-only, works in incognito, and never renders a card input.
  5. Checks the app reaches ready() within about three seconds on a warm load.

The guidelines

Design

  • Built on Folio: the stylesheet or the starter’s components, and the CSS variables rather than hardcoded colours. Tested in dark mode and under a white-label tint.
  • No header of your own: the dashboard draws it. Declare crumbs and actions through titleBar().
  • Full pages for create and edit flows. Popups are for confirmations and short forms, and are rendered by the dashboard.
  • A page never repeats the app’s name as its title, never wraps itself in a border or card, and opens with the section the merchant came for.
  • ready() is called as soon as something can be shown.

Authentication and security

  • Every ID token claim validated; the workspace read from the verified token.
  • A fresh token per request; the client secret only ever on your server.
  • Content-Security-Policy: frame-ancestors https://paysio.com https://{host}; on every framable response, where host is the base64-decoded parameter. This is what stops a hostile page framing your app and driving a signed-in merchant.
  • https only. No third-party cookies. Works in incognito.
  • Never a card input, never card data. Not a PAN, not a CVC, not bank credentials. Payments go through checkout sessions and payment links. This is the one rule with no discretion: it breaks the merchant’s PCI compliance, so it is rejected on sight and suspended if found live.

Data

  • The narrowest scopes that work, with optional ones marked optional.
  • app/uninstalled honoured: that workspace’s data deleted or anonymised on your side.
  • A privacy policy, linked from the listing.
  • Documented APIs only. Undocumented endpoints change without notice.

Sandbox

  • The mode read from the claim and honoured: no real-world action on a test event.
  • Your own records kept separate per mode, and a badge saying which mode is active.

Performance and support

  • ready() within about 3 seconds on a warm load; a lean initial payload.
  • A monitored support email on the listing, and a stated response time.

Listing

FieldRequirement
Name30 characters or fewer, distinctive, no “for Paysio” suffix.
Tagline100 characters or fewer. What it does, in one line.
DescriptionWhat it does and who it is for. Plain language.
Features80 characters or fewer each, scannable.
IconSquare, your own mark. Shown in the sidebar, the store and the header crumb.
Screenshots1600×900, real states of the app. Not mockups, not marketing collateral.
ChangelogRequired on every released version. Renders as “What’s new”.

Scopes are shown to merchants from your config, never from your copy.

Prohibited

  • Proxying or reselling API access.
  • Harvesting credentials of any kind.
  • Bulk export of personal data beyond the app’s stated purpose.
  • Misrepresenting what a scope is used for.
  • Apps whose primary function is circumventing platform rules.

What re-review gates

We cannot review code that lives behind a URL you control, so we do not pretend to. What is reviewed is the configuration that bounds the app:

ChangeRe-review?
Code behind your URLNo. Deploy freely.
Listing contentYes.
Adding a scopeYes. Inert until approved; merchants then see the diff and re-consent.
Changing your app’s originYes. Merchants keep loading the approved origin until the new one is approved.
Removing a scope, making one optionalNo.

Versions

Every submission is a version: a snapshot of your configuration, with a changelog. What merchants see — the listing, the scopes they are asked to grant, the origin they load — is always the state a reviewer approved, even while you are editing a draft of the next one. Versions move through draft → submitted → approved → released, or rejected with a reason you can address and resubmit.

Suspension

The compensating control for un-reviewable code. Suspending an app revokes every live token, stops the embed loading and hides its customer-facing blocks, in every workspace, on the next request. It is used for the prohibited list above, for a security incident, and for an app that breaks the card-data rule. You are contacted at your support email; a resolved cause is reinstated.

Uninstalls

Subscribe to app/uninstalled and delete that workspace’s data when it fires. Anything you stored with us — app data, blocks — is kept for 30 days and then purged, so a merchant who removed the app by mistake can reinstall and find their settings intact. Your offline tokens for that workspace are revoked the moment the uninstall happens.