Getting Started

Everything you need to authenticate, make your first API call, and start building with the SpireStock REST API.

Prerequisites

  • An active SpireStock workspace with admin or developer access.
  • An API key, created from the dashboard under Developer β†’ API Keys. Creating one requires workspace administrator access.
  • A tool for making HTTP requests β€” cURL, Postman, or any HTTP client library.
πŸ’‘

Don't have a workspace yet?

Sign up at app.spirestock.com/signup to create a free workspace and start building immediately.

Base URL

All API endpoints are served from a single base URL. Every path referenced in this documentation is relative to:

https://api.spirestock.com/api/v1

For example, the full URL for listing orders would be https://api.spirestock.com/api/v1/orders.

Authentication

SpireStock accepts two credentials. Which one you want depends on whether a browser is involved.

CredentialUse it forLifetime
API key β€” X-API-KeyServers, scheduled jobs, ERP connectors, anything without a browserUntil you revoke it (or its optional expiry)
JWT β€” Authorization: BearerBrowser sessions signed in through the dashboard15 days, and only one active per user
⚠️

Server-side? Use an API key.

/auth/login requires a Cloudflare Turnstile token, which only a browser can obtain β€” a server calling it gets 400 Security verification required. On top of that, a user holds only one valid JWT at a time, so signing into the dashboard invalidates the token your integration was using. API keys have neither problem.

Authenticating with an API key

Create a key in the dashboard under Developer β†’ API Keys, or with the API itself while signed in as an administrator:

Create a key
curl -X POST https://api.spirestock.com/api/v1/developer/api-keys \
  -H "Authorization: Bearer YOUR_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Warehouse sync",
    "scopes": "read,orders",
    "expires_in_days": 90
  }'
Response (201 Created)
{
  "response_code": 201,
  "message": "API key created. Save this key β€” it won't be shown again.",
  "data": {
    "id": 3,
    "key": "df_9f3a1c7e2b8d4a6f0c5e1b7a3d9f2e4c6a8b0d2f4e6a8c0b2d4f6a8c0e2b4d6f",
    "name": "Warehouse sync",
    "key_prefix": "df_9f3a1c",
    "scopes": "read,orders",
    "expires_at": "2026-11-16T00:00:00.000Z"
  }
}
🚨

The key is shown exactly once

Only a SHA-256 hash of the key is stored, so it cannot be retrieved later β€” not by you, not by support. Save it to your secret store the moment you create it. Lost a key? Revoke it and issue a new one.

Send it on every request as a header:

X-API-Key: df_9f3a1c7e2b8d...

Scopes

A key’s scopes string mixes two kinds of token: actions (read, write) and optional resources (orders, users, products, …). read permits GET and HEAD; write permits every method and implies read. Name no resource and the key reaches every endpoint it is allowed to; name one or more and it is confined to those.

ScopesWhat the key can do
readRead any endpoint
read,ordersRead /orders and nothing else
write,ordersFull access to /orders, read and write
read,writeFull access to every allowed endpoint
*The same as read,write
πŸ’‘

Endpoints an API key cannot reach

Regardless of scope, keys are refused on /auth, /signup, /developer, /platform, /super-admin, /portal, /driver-app and /support. That is why key and webhook management needs a signed-in administrator β€” a leaked key cannot mint more keys or repoint your webhooks.

Authenticating with a session token

If you are building something a person signs into, exchange their credentials for a JWT. The request must carry a turnstile_token from the Turnstile widget on your page:

Request
curl -X POST https://api.spirestock.com/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -H "User-Agent: AcmeIntegration/1.0" \
  -d '{
    "email": "YOUR_EMAIL",
    "password": "YOUR_PASSWORD",
    "turnstile_token": "TOKEN_FROM_THE_TURNSTILE_WIDGET"
  }'
Response (200 OK)
{
  "response_code": 200,
  "message": "Login successful",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "user": {
    "id": 1,
    "first_name": "Jane",
    "last_name": "Developer",
    "official_email": "[email protected]",
    "role_name": "Admin",
    "user_type": 0,
    "organization_id": 5,
    "organization_name": "Acme Dairy"
  },
  "workspace": {
    "workspace_id": "ws_x9y8z7",
    "slug": "acme-dairy",
    "display_name": "Acme Dairy",
    "plan": "professional",
    "status": 1
  }
}

Include the token in the Authorization header using the Bearer scheme:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
⚠️

Token expiry & single active session

Tokens expire after 15 days. Only one is valid per user at a time β€” logging in again, logging out, or changing the password invalidates the previous one. When you receive 401 Unauthorized, re-authenticate.

🚨

Token storage best practices

Never store JWT tokens in localStorage or sessionStorage β€” they are accessible to any JavaScript running on the page (XSS-vulnerable). Instead:

  • Server-side apps: Store tokens in memory or encrypted server-side sessions.
  • Browser apps: Use httpOnly cookies set by your backend proxy, or keep tokens in memory only (they will be lost on page refresh, which is the safer trade-off).
  • Never include tokens in URLs, log files, or error reporting payloads.

Set a User-Agent

The API rejects requests whose User-Agent is missing, shorter than 10 characters, or matches a known scraping tool. Several HTTP clients trip this by default:

ClientSends by defaultResult
cURLcurl/8.5.0403
Python requestspython-requests/2.31.0403
Node fetchnode (4 characters)403
βœ…

Two ways to satisfy this

Send X-API-Key β€” keyed requests skip the check entirely, because the key already identifies you. Or set a descriptive User-Agent naming your integration, which is good practice either way:

Identifying your client
curl https://api.spirestock.com/api/v1/orders \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "User-Agent: AcmeIntegration/1.0"

Your First Request

With a key in hand, fetch a list of orders from your workspace. Keep the key in an environment variable β€” never in source control.

GET /orders
curl https://api.spirestock.com/api/v1/orders \
  -H "X-API-Key: $SPIRESTOCK_API_KEY"

Every request is scoped to the organization the key belongs to. There is no tenant parameter to pass and no way to reach another workspace’s data.

Rate Limits

To ensure fair usage across all tenants, the API enforces rate limits on a per-IP or per-token basis. When a limit is exceeded the API responds with 429 Too Many Requests.

Endpoint GroupLimitWindow
POST /signup/register5 requestsPer hour
POST /auth/login20 requestsPer 15 minutes
General endpoints120 requestsPer minute
General endpoints2,000 requestsPer hour
Export endpoints5 requestsPer minute
Report endpoints20 requestsPer minute
πŸ’‘

Rate-limit headers

Every response includes X-RateLimit-Limit and X-RateLimit-Remaining so you can throttle before you are throttled. A 429 also carries Retry-After in seconds.

βœ…

Each key gets its own budget

An API key is metered separately from the administrator who created it, and separately from every other key. A busy integration cannot rate-limit a colleague out of the dashboard, and splitting work across two keys gives you two budgets.

Error Handling

The API uses standard HTTP status codes. Errors include a JSON body with a response_code matching the HTTP status and a human-readable message field.

Error response example
{
  "response_code": 400,
  "message": "Validation failed"
}
Status CodeMeaningCommon Cause
400Bad RequestInvalid or missing request body fields
401UnauthorizedMissing, revoked, or expired credential
403ForbiddenMissing scope, an endpoint API keys cannot reach, a suspended workspace, or a rejected User-Agent
404Not FoundResource does not exist or belongs to another workspace
429Too Many RequestsRate limit exceeded β€” back off and retry
500Internal Server ErrorUnexpected server-side failure β€” contact support if it persists

Next Steps

Now that you can authenticate and make requests, explore further:

  • API Reference β€” Full endpoint documentation with request/response schemas.
  • Webhooks β€” Receive real-time event notifications for orders, users, and payments.
  • SDKs β€” Official client libraries for Node.js, Python, and cURL examples.