Skip to content

Authentication

All API requests require a Bearer token. Keys belong to your account and carry a Projects field — every project, or the ones you pick — and begin with sk_live_ or sk_sandbox_.

One key type, two habits

A key that reaches all projects is the one you give your coding agent: it can list and create projects, and it keeps working for projects you add later. A key limited to one project is the one you put inside that app's .env: if it ever leaks, it exposes one product, not all of them.

Which project a request acts on

Project-scoped endpoints (tickets, emails, articles, logs, feedback, customers, webhooks) act on one project. Name it with the Helmdesk-Project header or ?project=<slug-or-id>. A key that can reach exactly one project needs neither. A key that can reach several and names none gets 400 project.required with the choices listed — the API never guesses which project you meant.

curl -H "Authorization: Bearer sk_live_abc123..." \
  -H "Helmdesk-Project: ledgerly" \
  https://helmdesk.dev/api/v1/tickets

# or, without the header:
curl -H "Authorization: Bearer sk_live_abc123..." \
  "https://helmdesk.dev/api/v1/tickets?project=ledgerly"

GET /v1/projects lists the projects a key can reach. Keys with the api_keys:manage scope can mint further keys with POST /v1/api-keys — only for projects and scopes the minting key itself holds.

Which environment a request acts on

The key prefix bounds the data plane: an sk_sandbox_ key is always sandbox. An sk_live_ key is live unless the request sends Helmdesk-Environment: sandbox (or ?environment=sandbox), which routes that one request to the sandbox plane — nothing sent from sandbox reaches a real inbox. A sandbox key asking for live gets 403 environment.forbidden. See the sandbox guide.

curl -H "Authorization: Bearer sk_live_abc123..." \
  -H "Helmdesk-Project: ledgerly" \
  -H "Helmdesk-Environment: sandbox" \
  -X POST https://helmdesk.dev/api/v1/tickets -d '{ ... }'

Using the SDK

Pass your API key when creating the client. The SDK handles the Authorization header automatically.

import { HelmdeskClient } from '@helmdesk/sdk'

const helmdesk = new HelmdeskClient({
  apiKey: process.env.HELMDESK_API_KEY!,
  // Optional: pin a project for a multi-project key. Read from
  // HELMDESK_PROJECT when omitted.
  project: process.env.HELMDESK_PROJECT,
})

// Act on another project for one call chain:
await helmdesk.withProject('nightjar').tickets.list()

Using curl / fetch

Include the key in the Authorization header:

curl -H "Authorization: Bearer sk_live_abc123..." \
  https://helmdesk.dev/api/v1/tickets

Managing keys

Create, edit, and revoke API keys from Admin Settings → API keys(owners and admins). Each key shows the projects it reaches; a project's settings link opens the same page filtered to that project. If a key is compromised, revoke it immediately and create a new one.

The dashboard account behind those keys can be protected too: turn on two-factor authentication (a TOTP authenticator app) from Settings → Profile, after which every sign-in asks for a code, and a sign-in from an unfamiliar browser triggers a “New sign-in” email. See the security page.

Creating and revoking keys through the API

A key with the api_keys:manage scope (outside every preset — grant it deliberately) can mint and revoke keys for the account. A minted key can only reach projects the caller reaches and only hold scopes the caller holds, and it lives in the caller's environment unless environment says otherwise: a live key may pass "sandbox" to mint a sandbox key for an app's dev config, while a sandbox request can never mint a live key (403). Revoking is permanent — the key stops authenticating on its next request and every app using it stops working — and a key cannot revoke itself (409): use another key or the dashboard.

// Mint a sandbox key for the app's dev config (from a live key)
curl -X POST https://helmdesk.dev/api/v1/api-keys \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"name":"ABC Salon dev","projects":["abc-salon"],"scopes":["emails:send","logs:write"],"environment":"sandbox"}'
// → { "id": "...", "key": "sk_sandbox_...", "environment": "sandbox", ... }  (key shown once)

// Revoke a key by id — DELETE /v1/api-keys/:id
curl -X DELETE https://helmdesk.dev/api/v1/api-keys/<key-id> \
  -H "Authorization: Bearer sk_live_..."
// → { "revoked": true, "id": "...", "name": "ABC Salon dev" }

// SDK
const dev = await helmdesk.apiKeys.create({ name: 'ABC Salon dev', projects: ['abc-salon'], environment: 'sandbox' })
await helmdesk.apiKeys.revoke(dev.id)

Security note

Never expose your API key in client-side code or commit it to version control. Use environment variables and keep your keys server-side.