API Reference
Authentication
SquirrelStack uses API keys passed via the X-Api-Key header,
or personal access tokens (PATs) via Authorization: Bearer pat_….
Server-side integrations typically use the secret key. Personal tools (the CLI, the SquirrelStack Mac app)
use a PAT scoped to a user — see CLI docs for details.
PAT requests need an account header
A PAT identifies a user, not an account. For endpoints that act on account data (dashboard, activity, errors, metrics summary), include
X-Account-Slug: <slug> to pick which account to operate on.
If your user belongs to exactly one account, the header is optional and that account is used by default.
If your user belongs to multiple accounts and no slug is sent, the API returns
400 with a list of available slugs in available_accounts.
Use GET /api/v1/me to discover what's available.
Site Key
Used for client-side tracking and chat widget endpoints. Safe to include in front-end code.
your_site_key
Secret Key
Used for server-side endpoints (subscriptions, custom metrics, deals). Keep this private.
your_secret_key
Sign in to see your actual API keys.
Base URL
https://squirrelstack.app/api/v1/
Request Format
All request and response bodies are JSON. Include these headers with every request:
Content-Type: application/json
X-Api-Key: your_api_key_here
Or with a personal access token:
Content-Type: application/json
Authorization: Bearer pat_xxx
X-Account-Slug: your_account_slug
Current User
/api/v1/me
PAT
Returns the authenticated user and the accounts they belong to. Used by clients (CLI, Mac app) to populate an account picker. Does not require X-Account-Slug.
Success Response (200)
{
"user": { "id": 1, "name": "Jane Doe", "email": "jane@example.com" },
"accounts": [
{ "slug": "acme", "name": "Acme Inc", "icon_url": "https://squirrelstack.app/rails/active_storage/..." },
{ "slug": "beta", "name": "Beta Co", "icon_url": null }
]
}
icon_url is an absolute URL to the
account's square icon (a normalised PNG), or null
when no icon has been uploaded — clients should render a monogram fallback. The URL changes whenever the icon
changes, so it is safe to cache by URL.
Error Responses
Errors return the appropriate HTTP status code with a JSON body:
{
"error": "A single error message"
}
// or for validation errors:
{
"errors": [
{ "entity": "subscription", "index": 0, "message": "..." }
]
}
| Status | Meaning |
|---|---|
| 401 | Missing or invalid API key |
| 403 | Origin not allowed |
| 404 | Resource not found |
| 422 | Validation error |
| 429 | Rate limit exceeded |
| 500 | Internal server error |
Rate Limiting
Some endpoints enforce per-IP rate limits. When exceeded, you'll receive a 429 Too Many Requests response.
| Endpoint | Limit |
|---|---|
| POST /tracking/visits | 30 req/min |
| POST /tracking/events | 60 req/min |
| GET /chat/config | 60 req/min |
| POST /chat/conversations | 5 req/min |
| GET /chat/.../messages | 60 req/min |
| POST /chat/.../messages | 20 req/min |
| POST /monitor/heartbeat/:token | 60 req/min |
| GET /activity | 30 req/min |
| GET /metrics_summary | 30 req/min |
| GET /metrics/web | 30 req/min |
| GET /metrics/web/visits | 30 req/min |
| GET /metrics/web/events | 30 req/min |
| /errors/* | 30 req/min |
| POST /helpdesk/tickets | 10 req/min |
| GET /helpdesk/tickets/:ticket_id/messages | 60 req/min |
| GET /tickets | 30 req/min |
| GET /tickets/:id | 30 req/min |
| /crm/list_memberships | 30 req/min |
| POST /projects/:project_id/notices | 100 req/min |