Create, configure, submit and publish an app in the spuke App Store.
From draft to a complete listing.
Apps are created straight from the dashboard: Apps → New app creates an Untitled app draft and opens the publishing wizard. Nothing is public until you submit and we approve.
The wizard
| Step |
What you fill in |
| App basics |
Name, tagline, category, description |
| Branding & media |
Icon, screenshots |
| Availability & pricing |
Markets, setup effort, EUR pricing |
| Links & compliance |
Website, support, privacy policy, data handling |
| OAuth & webhooks |
Redirect URIs, credentials, event subscriptions |
| Submit for review |
Version number, requested scopes, notes for the reviewer |
Every step saves as you continue — there is no separate save button.
Naming rules
- 3–40 characters, unique in the App Store.
- No "spuke" prefix, no other brand names you do not own.
- The tagline is one sentence, sentence case, no marketing punctuation.
Description that passes review
Cover: what the app does, which merchants it is for, what happens after install, and which data it reads. Reviewers reject descriptions that only list features without explaining the merchant outcome.
Media requirements
| Asset |
Requirement |
| Icon |
Square PNG, at least 512×512, no rounded corners baked in |
| Screenshots |
2–6, 16:9, real product UI — no mockups with fake numbers |
Deleting a draft
Drafts, rejected apps and apps with changes requested can be deleted while they have 0 installations. Published apps cannot be deleted; unpublish them instead so existing merchants keep working.
What we check, how long it takes and how to pass first time.
Submitting
Submitting freezes a version: listing content plus the requested scopes. The app moves to in_review and the listing becomes read-only until we respond.
Statuses
| Status |
Meaning |
draft |
Work in progress, only visible to your organization |
in_review |
Submitted, waiting for a reviewer |
changes_requested |
Fixable issues — edit and resubmit |
rejected |
Not eligible in its current form |
published |
Live in the App Store |
unpublished |
Hidden from the store, existing installs keep working |
What reviewers check
- Scope hygiene — every requested scope is justified by the described functionality. Asking for
payments:create for a reporting app is the most common rejection.
- Working install — the OAuth flow completes against a real redirect URI and the app renders something useful.
- Listing accuracy — screenshots show the actual product, pricing matches what you charge.
- Legal pages — reachable privacy policy and support contact, and a data-handling statement.
- Webhook health — your endpoint answers
2xx within 10 seconds during the test delivery.
- Stability — no error spikes in your sandbox logs for the submitted version.
Timing
Reviews are usually answered within 3 business days. Resubmissions after changes requested are prioritized.
Publishing
On approval:
- in live mode the one-time publishing fee is charged to your billing method;
- the listing goes public in the App Store;
- merchants can install immediately.
Publishing is blocked while your payout account is restricted or disabled.
Updating a published app
Editing a published listing creates a new version in draft. The live listing keeps serving until the new version is approved. Adding new scopes requires re-consent: existing installations keep the old scopes until the merchant approves the update.
The authorization code flow with PKCE, step by step.
Merchants install your app through OAuth 2.0 — authorization code with PKCE. No client secret is ever needed in a browser.
1. Send the merchant to consent
https://spuke.com/oauth/authorize
?client_id=app_live_123
&redirect_uri=https://yourapp.com/callback
&response_type=code
&scope=merchant:read%20payments:read
&state=<random>
&code_challenge=<base64url(sha256(verifier))>
&code_challenge_method=S256
The merchant sees your icon, name and a plain-language list of every scope with its risk level, then approves or declines.
2. Exchange the code
curl -X POST https://api.spuke.com/v1/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "authorization_code",
"code": "ac_…",
"redirect_uri": "https://yourapp.com/callback",
"client_id": "app_live_123",
"code_verifier": "…"
}'
{
"access_token": "spat_live_…",
"refresh_token": "sprt_live_…",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "merchant:read payments:read",
"installation_id": "inst_live_7c1f92a8",
"mode": "live"
}
Store the tokens per installation, never globally.
3. Refresh
{ "grant_type": "refresh_token", "refresh_token": "sprt_live_…", "client_id": "app_live_123" }
Refresh tokens rotate: the response contains a new refresh token and the old one dies. If a refresh returns invalid_grant, treat the installation as gone and stop calling.
Redirect URI rules
- HTTPS only, exact match, no wildcards.
http://localhost is allowed in test mode.
- Up to five URIs per app.
- Changing a URI on a published app requires a new version.
Uninstall
When a merchant uninstalls, tokens are revoked immediately and you receive an installation.uninstalled webhook. Delete the merchant's data within 30 days unless law requires otherwise.
Suspension
If a merchant is suspended, API calls for that installation return 403 installation_suspended. Back off and retry later — do not delete data on a suspension.