API authentication
Every Storlaunch API request must include an API key. We use a plain Authorization: Bearer scheme — no request signing, no timestamping, no idempotency-key hashing. The key itself is the credential.
This page covers the exact recipe and the security model. If you're using one of our SDKs (Node, Python, Go), the key is set once at client construction and added to every request automatically.
TL;DR
For every request:
- Mint an API key in the dashboard.
- Send it as
Authorization: Bearer <key>on every request. - That's it.
curl https://storlaunch.forjio.com/api/v1/storefront/products \
-H "Authorization: Bearer sk_test_xxxxxxxxxxxxxxxxxxxxxxxx"
The key types
Storlaunch issues two kinds of keys, each in two environments:
| Prefix | Environment | Access | Used for |
|---|---|---|---|
pk_test_… |
Test | Read-only public data (products, storefront) | Frontend code in development |
pk_live_… |
Live | Read-only public data (products, storefront) | Frontend code in production |
sk_test_… |
Test | Full account access | Backend integration in development |
sk_live_… |
Live | Full account access | Backend integration in production |
Publishable keys (pk_*) are safe to embed in client-side JavaScript — they only allow reads on public data (your storefront's product catalog). Storlaunch's auto-generated storefronts use them.
Secret keys (sk_*) grant full read/write on the workspace. Server-only. Anyone with one can place orders, refund payments, change settings.
Generate one
In the dashboard, navigate to Settings → API keys (or /dashboard/api-keys).
Click Create API key:
- Pick a name (e.g., "Production webhook handler").
- Pick an environment: Test or Live.
- Pick an access level: Publishable (read-only public) or Secret (full access).
Storlaunch shows the key value once. Copy it into your environment manager immediately.
The key appears only once. When you create a key, Storlaunch shows it in a dialog. If you close it without copying, you have to mint a new key. There's no recovery flow.
Sending the header
Every authenticated request has one header:
Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx
If you're sending a body (POST/PUT/PATCH), also send Content-Type: application/json.
Optional headers worth knowing:
| Header | Purpose |
|---|---|
X-Account-Id |
Override which workspace this request operates on (for users who are members of multiple). Defaults to the key's home workspace. |
Idempotency-Key |
Make a mutation safely retryable. Same key within 24h returns the same response. |
User-Agent |
We log this; it helps us debug. Use something descriptive like my-app/1.0. |
A complete curl example
export STORLAUNCH_API_KEY=sk_test_xxxxxxxxxxxxxxxxxxxxxxxx
# List products
curl https://storlaunch.forjio.com/api/v1/storefront/products?limit=5 \
-H "Authorization: Bearer $STORLAUNCH_API_KEY"
# Create a product
curl -X POST https://storlaunch.forjio.com/api/v1/storefront/products \
-H "Authorization: Bearer $STORLAUNCH_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: product-import-2026-05-12-001" \
-d '{
"name": "Concert ticket",
"price": 250000,
"currency": "IDR",
"type": "digital"
}'
Why not HMAC?
Plugipay (also in the Forjio family) uses HMAC-SHA256 request signing because payment APIs sign every individual request to defend against replay and tampering — the upside is large because the operations are financially sensitive.
Storlaunch's surface is e-commerce operations: products, orders, fulfilment. The replay risk is lower (you can't double-place an order easily, and idempotency keys handle the legitimate retry case), the integration surface is broader, and the value of "easier to integrate" is higher.
So we picked bearer tokens for Storlaunch and accept the trade-off. Treat your secret key like a password — transport-encrypted (HTTPS), stored in a secret manager, rotated periodically.
Storlaunch as a Plugipay partner
Under the hood, Storlaunch is a Plugipay partner — every time your storefront takes a payment, Storlaunch calls Plugipay's API on behalf of your workspace's auto-provisioned Plugipay account.
You don't see this; it's an internal detail. But it does mean:
- You don't need a separate Plugipay API key to operate your Storlaunch store. The Storlaunch key is sufficient.
- The Plugipay-backed routes (
/api/v1/payment/*) accept your Storlaunch key — Storlaunch translates them into Plugipay calls with the appropriateX-Plugipay-On-Behalf-Ofheader. - Plugipay webhooks flow to Storlaunch first (
/api/v1/webhooks/plugipay); Storlaunch normalizes them and re-emits Storlaunch-shaped events to your webhook endpoints.
If you want to call Plugipay directly — for an advanced flow not exposed via Storlaunch — you can mint a Plugipay key in the Plugipay dashboard under your auto-provisioned Plugipay workspace.
Multi-workspace keys
A key is scoped to the workspace it was created in. To call the API for a different workspace, mint a key in that workspace.
If you're a platform admin operating many merchant workspaces, you'll have one key per workspace. Storlaunch doesn't currently expose a "platform-level" key that can scope per-request via a header — this is a feature on the roadmap, not shipped.
Security model
A few rules to live by:
- Treat
sk_*keys like passwords. Anyone with one can take any action on the workspace. - Never embed
sk_*in frontend code. Usepk_*for client-side reads of public data. Storlaunch enforces this server-side — apk_*key sent against a write endpoint returns403 INSUFFICIENT_PERMISSIONS. - Don't log keys. Truncate to last-4 in any logs you keep.
- Rotate periodically. From Settings → API keys, click an existing key and Rotate. The old value continues to work for a 24-hour grace period; we email the workspace owner.
- Revoke immediately if compromised. Revoking is instantaneous — no grace.
Webhook signatures vs API keys
This page covers outbound API requests (your code → Storlaunch). Storlaunch also signs inbound webhooks (Storlaunch → your endpoint) with a separate HMAC-SHA256 scheme using the X-Storlaunch-Signature header.
Webhook signing keys are minted per webhook endpoint, not per API key, and are independent. See API → Webhooks (coming soon) for the verification recipe.
Common errors
401 AUTHENTICATION_REQUIRED
No Authorization header was present, or it didn't start with Bearer . Check that:
- The header is exactly
Authorization: Bearer <key>(case-sensitive onBearer). - The key isn't empty.
- There's no extra whitespace on either side.
401 INVALID_API_KEY
The key is malformed, was revoked, or doesn't exist. Verify:
- It matches one in Settings → API keys.
- It hasn't been revoked (revoked keys show a strikethrough in the UI).
- You're not mixing test and live keys with the wrong environment.
403 INSUFFICIENT_PERMISSIONS
The key is valid but doesn't have access to this operation. Most common cause: using a pk_* (publishable) key on a write endpoint. Use an sk_* key.
429 RATE_LIMITED
You exceeded the per-workspace rate limit. Check the Retry-After header and back off.
Next
- API overview — the envelope, pagination, idempotency.
- SDKs — if you'd rather not write the HTTP yourself.
- Authentication overview — the browser-side OIDC flow (different model, different audience).