Authentication
API keys
GoSendAPI uses per-project API keys. Each key is scoped to a single project — it can read and write only that project’s data.
Keys come in two environments:
| Prefix | Environment | What it does |
|---|---|---|
gsk_test_ | Sandbox | Returns synthetic responses without calling Meta. Useful for testing your integration code (request shape, error handling, idempotency, etc.) without spending quota or spamming real recipients. |
gsk_live_ | Production | Routes through your real WABA + phone numbers. Real delivery to WhatsApp. Counts against your plan’s monthly quota. |
Both share the same API surface — only the side effect differs.
Sandbox is a stub, not Meta’s test number. When you send via a gsk_test_* key, the API returns a synthetic response (wa_message_id: wamid.SANDBOX.xxx, status: sent_sandbox) without calling Meta. This means:
- Your integration code (HTTP plumbing, idempotency, error handling) works identically test vs live
- The recipient never receives a real WhatsApp message in sandbox mode
- No persistence in DB (sandbox messages don’t show up in
GET /v1/messages)
For end-to-end testing with real delivery (e.g. to your own WhatsApp number), use a gsk_live_* key with a WABA already onboarded.
How to authenticate
Pass the key in the X-API-Key header on every request:
curl https://cloud.gosendapi.com/v1/me \
-H "X-API-Key: gsk_live_..."A valid key returns 200 OK with the project info:
{
"id": "42",
"name": "Acme Production",
"webhookUrl": "https://api.acme.com/webhooks/gosendapi",
"createdAt": "2026-01-15T10:00:00Z"
}An invalid or missing key returns 401 Unauthorized:
{
"statusCode": 401,
"message": "Invalid or missing API key",
"error": "Unauthorized"
}Creating and rotating keys
API keys are managed from the dashboard at app.gosendapi.com → API Keys.
Create a new key
Click Create key, give it a label (e.g. backend-prod, worker-bills). The full key is shown only once — copy it immediately.
Use the key
Set it as an environment variable in your application:
GOSENDAPI_KEY=gsk_live_a1b2c3d4e5f6...Never hardcode keys in your source code or commit them to git.
Rotate when needed
If a key is compromised, or on a regular schedule (every 90 days is a healthy default), click Rotate. A new key is generated; the old one stops working immediately.
Revoke when retired
For keys you no longer use (decommissioned services, temporary integrations), click Revoke. The key becomes invalid permanently.
Multiple keys per project
You can have many active keys per project — useful for:
- Per-service keys: one for your backend, one for your worker queue, one for a Slack bot. Easier to revoke when a single service is compromised.
- Per-environment: a
gsk_test_*for staging and agsk_live_*for production, both in the same project. - Per-team: if you offer access to contractors, give them their own key you can revoke later.
Each key has its own last-used timestamp visible in the dashboard, so you can spot stale keys.
Security best practices
Treat API keys like passwords. Anyone with the key can send messages on your behalf and read your data.
- Store in environment variables (
.env, secrets manager, K8s secrets, Vercel/Netlify env vars) — never in code. - Don’t expose to the browser. The API key must stay server-side. If you need to send from the client, proxy through your own backend.
- Use sandbox keys in development. Don’t share production keys across local machines.
- Rotate after departures. When a team member with key access leaves, rotate.
- One key per integration. Per-service keys let you revoke surgically without breaking everything.
- Enable IP allowlist (coming soon) to restrict keys to specific source IPs.
What about admin keys?
If you’re a platform partner with super-admin access, you’ll also see references to X-Admin-Key in the API. Those are reserved for operations like provisioning new tenants and are out of scope for normal customer integrations.
If you think you need admin access, contact us at hello@gosendapi.com.