Reference & support

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

Scope reference

Every permission, with its risk level.

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.
create / capture / cancel Narrow, money-moving actions that are granted separately.

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, currency Show whose account you are connected to Low
payments:read List and view payments Order sync, reporting, reconciliation Low
payments:create Start new payments Custom checkout, POS terminal High
payments:capture Capture a previously authorized payment Ship-then-charge flows High
payments:cancel Release an uncaptured authorization Cancelled orders High
refunds:read View refunds Returns dashboards Low
refunds:create Issue refunds — moves money out Returns automation High
customers:read Read buyer records (personal data) CRM sync Medium
customers:write Create and update buyers Two-way CRM sync Medium
products:read Read catalog and prices Storefront, catalog sync Low
products:write Create and update products/prices Catalog management, PIM Medium
invoices:read Read invoices Accounting export Low
invoices:write Create, send and void invoices Invoicing tools Medium
subscriptions:read Read subscriptions Churn analytics, entitlements Low
subscriptions:write Change plans, quantities, cancel Subscription management High
disputes:read Read disputes and deadlines Chargeback alerting Medium
disputes:write Submit or update evidence Chargeback automation High
payouts:read Read payouts and bank settlement data Bank reconciliation Restricted
analytics:read Aggregated volume figures Dashboards Low
webhooks:read Read the merchant's webhook configuration Diagnostics Low
webhooks:write Manage webhook endpoints 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. Ship the read-only version, add write scopes in a later version with a proven track record.
  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
installation_suspended Merchant or app suspended Back off, keep data
installation_uninstalled App was removed Stop calling, delete data
mode_mismatch Test token against live data or vice versa Use the right credentials
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.spuke.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:

Spuke-Deprecation: true
Spuke-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.