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
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 standsapps check runs exactly what review runs first, so a rejection is never a surprise. It fails on:
- No app URL, an
httpURL, 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:
- 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.
- Looks at the scope set and asks whether each one is needed for the described function.
- Opens the app in a sandbox workspace and exercises it: install, the first screen, the main flow, a popup, a mode switch, uninstall.
- Checks the frame headers, that the app is https-only, works in incognito, and never renders a card input.
- 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, wherehostis 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/uninstalledhonoured: 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
| Field | Requirement |
|---|---|
| Name | 30 characters or fewer, distinctive, no “for Paysio” suffix. |
| Tagline | 100 characters or fewer. What it does, in one line. |
| Description | What it does and who it is for. Plain language. |
| Features | 80 characters or fewer each, scannable. |
| Icon | Square, your own mark. Shown in the sidebar, the store and the header crumb. |
| Screenshots | 1600×900, real states of the app. Not mockups, not marketing collateral. |
| Changelog | Required 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:
| Change | Re-review? |
|---|---|
| Code behind your URL | No. Deploy freely. |
| Listing content | Yes. |
| Adding a scope | Yes. Inert until approved; merchants then see the diff and re-consent. |
| Changing your app’s origin | Yes. Merchants keep loading the approved origin until the new one is approved. |
| Removing a scope, making one optional | No. |
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.