Reference & support

Scopes, security requirements, limits and how to reach us.

Scope reference

Every permission, with its risk level.

What is callable today: all *:read scopes in the endpoint list, plus the write scopes products:write, files:write, orders:write and subscriptions:write (subscription links). Only scopes explicitly marked (not callable in v1) below are unavailable. The Store scopes store:read, products:read, products:write, files:write, orders:read and orders:write are callable in v1 through the routes listed in Endpoints. The callable surface is always the list in Endpoints.

A scope is a single permission. Your app can only touch data a merchant explicitly granted. Scopes are shown on the consent screen with their risk level, so over-asking directly costs you installs — and reviewers compare your scope list against what your app actually does.

Naming

resource:action — e.g. payments:read = "list and view payments".

Action Means
read List and retrieve objects. Never changes anything.
write Create and update objects of that resource.

Risk levels

Risk Meaning
Low Read-only, no personal or money-moving data. Approved by default.
Medium Personal data or configuration changes. Needs a clear reason in your listing.
High Moves or reverses money. Written justification at review, extra security checks.
Restricted Financial reporting data. Granted case by case and revocable.

Catalog

Scope What it lets your app do Typical use case Risk
merchant:read Read the merchant profile: name, country, city, VAT number, status, plan Show whose account you are connected to Low
payments:read List and view payments Order sync, reporting, reconciliation Low
refunds:read View refunds Returns dashboards Low
customers:read Read buyer records (personal data). No /customers endpoint in App API v1 — buyer name and email are returned inline on payments, invoices and subscriptions CRM sync Medium
customers:write Create and update buyers (not callable in v1; no /customers route exists) Two-way CRM sync Medium
products:read Read the product catalog, option groups and variants Storefront, catalog sync Low
products:write Create, update and archive store products, prices, option groups, values and variants Catalog management, PIM, Shopify/ERP sync Medium
store:read Read the merchant's Southbill Store: name, slug, branding, status Storefront apps Low
files:write Upload product images, documents and covers (max 5 MB) Catalog sync with media Medium
orders:read Read store orders with customer, shipping and fulfillment state Order sync, fulfillment Medium
orders:write Update fulfillment/tracking and attach delivery evidence Shipping automation Medium
invoices:read Read invoices Accounting export Low
invoices:write Create, send and void invoices (not callable in v1 — invoices are read-only in the App API) Invoicing tools Medium
subscriptions:read Read subscriptions Churn analytics, entitlements Low
subscriptions:write Create, update and archive subscription links Subscription link automation High
disputes:read Read disputes and deadlines Chargeback alerting Medium
disputes:write Submit or update evidence (not callable in v1 — disputes are read-only in the App API) Chargeback automation High
payouts:read Read payouts, bank settlement data and /balance Bank reconciliation Restricted
analytics:read Aggregated volume figures Dashboards Low
webhooks:read Read the merchant's webhook configuration (not callable in v1 — app webhooks are configured in your developer dashboard) Diagnostics Low
webhooks:write Manage webhook endpoints (not callable in v1) Auto-setup during install Medium

Rules that trip people up

  1. Least privilege. Reviewers reject scope lists that don't match the described functionality.
  2. Read before write. Ask for Store write scopes only if your app really creates or updates catalog/order data.
  3. Adding a scope requires a new app version and re-consent from every merchant. Missing scopes only surface as 403 insufficient_scope at runtime — check the granted scopes after install and degrade gracefully.
  4. Restricted scopes can be revoked if we see misuse; your app must keep working without them.
  5. A missing scope returns 403 with error.type: "insufficient_scope" — see Error & status codes.

Error & status codes

Every code you can receive, and the correct reaction.

Envelope

{ "error": { "type": "insufficient_scope", "message": "Missing required scope: payments:read",
  "request_id": "req_9f21c" } }

Always log request_id — support can trace any call with it.

HTTP status map

Status Meaning Retry?
400 Malformed request or bad parameter No — fix the call
401 Token missing, expired or revoked Refresh once, then stop
403 Permission, suspension or mode problem No
404 Object not found for this merchant No
409 Conflicting state No — re-read, then decide
422 Semantically invalid No
429 Rate limited Yes, honour Retry-After
500/502/503 Our side Yes, exponential backoff with jitter

API error types

Type Cause Fix
invalid_request Unknown parameter, bad pagination value Correct the request
invalid_token Expired or revoked access token Refresh; on failure treat the install as gone
insufficient_scope Scope not granted Request it in a new version, re-consent
merchant_suspended The merchant's account is suspended (403) Back off, keep data
installation_inactive The installation was revoked or suspended (401) Stop calling, delete data
query_failed Backend query failed (500) Retry, then contact support with request_id
not_found Wrong id, or not this merchant's object Check the id
rate_limit_exceeded Quota exhausted Backoff per Retry-After
internal_error Unexpected failure Retry, then contact support with request_id

OAuth errors

Returned on the redirect (?error=…) or from the token endpoint.

Code Cause
access_denied Merchant declined consent
invalid_request Missing parameter, e.g. no code_challenge
invalid_client Wrong client id, or wrong mode
invalid_grant Code expired/used, refresh token rotated away, bad code_verifier
redirect_uri_mismatch URI is not an exact registered match
invalid_scope Scope unknown or not approved for your app
unsupported_grant_type Only authorization_code and refresh_token exist

Authorization codes are single-use and expire after 10 minutes.

Webhook-side failures

Your response Our behaviour
2xx Delivered, done
3xx Treated as a failure — we do not follow redirects
4xx Retried on the standard schedule
5xx / timeout (>10 s) Retried on the standard schedule
Failing 72 h continuously Endpoint auto-disabled, you are notified

Retry recipe

Retry only 429 and 5xx. Exponential backoff starting at 1 s, factor 2, max 5 attempts, plus random jitter of up to 250 ms.

Security requirements

Non-negotiables for every published app.

Credentials

  • Client secrets, refresh tokens and webhook secrets live server-side only.
  • Never log tokens. Redact Authorization headers.
  • Rotate credentials immediately if a laptop, repo or CI secret is exposed, and tell us.
  • MFA is enforced on your developer account before live keys are issued.

Data handling

  • Store only what your feature needs, and say so in the listing.
  • Delete a merchant's data within 30 days of uninstall unless retention is legally required.
  • Never resell or share merchant data, and never use it to train models without explicit written consent.
  • Honour deletion requests raised through the dashboard within the stated deadline.

Transport

  • HTTPS everywhere; TLS 1.2 minimum.
  • Exact-match redirect URIs, PKCE for every authorization.
  • Verify webhook signatures with a constant-time comparison.

Operational

  • Alert on 401/403/429 spikes and webhook failures.
  • Keep an incident contact reachable; we use the support email on the listing.
  • Report a suspected breach affecting merchant data within 24 hours.

Violations lead to the app being unpublished and, in serious cases, the organization being suspended.

Versioning & changelog

What can change, and how much warning you get.

API surface

The App API is versioned in the path: https://api.southbill.com/v1/app. A v1 route never changes meaning; incompatible redesigns ship as v2 and both run in parallel during the migration window.

Additive by default

These can ship any day without notice — build for them:

  • new fields on existing objects
  • new enum values (status, reason, failure_code)
  • new event types
  • new endpoints and new optional query parameters

Rules that keep you safe: ignore unknown fields, never fail on an unknown enum value, ignore unknown event types, never depend on field order or on the exact shape of an id.

Breaking changes

Removing a field, renaming one, changing a type, tightening a limit or retiring an event type are breaking. They are announced at least 90 days ahead by email to the developer contact, in the dashboard changelog and with a deprecation note in the affected docs page. During the window, both behaviours are available where technically possible.

App versions

Your own app is versioned separately: each submission freezes a listing plus a scope set. Published versions stay attached to the installations that consented to them, so adding a scope never silently widens an existing install — the merchant re-consents first.

Deprecation signals

Deprecated endpoints answer with a header for the whole notice period:

Southbill-Deprecation: true
Southbill-Sunset: 2026-12-01

Alert on that header in your logs — it is the earliest automated warning you get.

Changelog

The dashboard changelog lists every platform change with a date, a type (added / changed / deprecated / removed) and a migration note where one is needed. Subscribe to it from the developer dashboard.

Support & status

Where to look when something breaks.

Self-service first

Symptom Look here
Calls rejected Logs → status codes, then rate limits
Events missing Sandbox → webhook deliveries and subscriptions
Install fails Redirect URI exact match, PKCE verifier, mode of the client id
Payout not arriving Payout account status and the threshold

Platform status

Live and historical incidents are on the status page linked from the developer dashboard. Subscribe there to be paged before your merchants notice.

Contacting us

Open a ticket from Support in the developer dashboard. Include the app number, the mode, the installation id and a request id from the logs — with those three we usually answer in one round trip.

Target first response: one business day; review questions are answered inside the review thread.

Deprecations

Breaking changes are announced at least 90 days ahead by email and in the changelog, with a migration note. Additive changes — new fields, new event types — ship without notice, so build tolerant parsers.