developers
ES Sign up

Get started

Authentication

Every request carries a workspace API key. The key decides which workspace you talk to and what you can do in it.

Send the key as a Bearer token on every request:

header
Authorization: Bearer sk_live_...

Keys look like sk_live_ followed by 43 characters. heysteff stores only a hash: if you lose the secret it cannot be recovered; create another key or rotate the one you have.

Create a key#

  1. Sign in at app.heysteff.com.
  2. Go to Settings → Developers → API Keys and click New API key.
  3. Pick the minimum scopes your integration needs and, optionally, the IPs allowed to use it.
  4. Copy the secret into your secrets manager or an environment variable.

Scopes#

Every operation requires a scope. A key without it gets 403 forbidden. Give each integration only what it uses: a store that sends shipping updates does not need refunds:write.

ScopeAllowsEndpoints
messages:writeSend messages (text, files, templates, buttons, lists, locations and reactions) and mark them as read.POST /v1/messages
POST /v1/messages/{id}/read
conversations:readRead conversations and their messages.GET /v1/conversations
GET /v1/conversations/{id}
GET /v1/conversations/{id}/messages
GET /v1/messages/{id}
conversations:writeHand a conversation to a person, pause or resume the bot, and resolve it.POST /v1/conversations/{id}/escalate
POST /v1/conversations/{id}/bot
POST /v1/conversations/{id}/resolve
contacts:readRead contacts and lists.GET /v1/contacts
GET /v1/contact-lists
contacts:writeCreate contacts and add them to lists.POST /v1/contacts
POST /v1/contact-lists/{id}/members
campaigns:readRead a campaign status.GET /v1/campaigns/{id}
campaigns:writeCreate and trigger campaigns.POST /v1/campaigns
events:readRead the event stream.GET /v1/events
events:writeIngest events from your system.POST /v1/events
conversions:writeReport conversions for attribution.POST /v1/conversions
charges:writeCharge with a payment link.POST /v1/charges
refunds:writeRefund payments.POST /v1/refunds
sales:readRead the sales funnel.GET /v1/sales/funnel
reviews:readRead reviews.GET /v1/reviews
reviews:writeRequest reviews.POST /v1/reviews
automations:triggerTrigger flows.POST /v1/automation-flows/{id}/trigger
owner:writeSleep mode of a personal workspace.GET /v1/owner/sleep
POST /v1/owner/sleep
webhooks:readRead webhooks and their delivery log.GET /v1/webhooks
GET /v1/webhooks/{id}/deliveries
webhooks:writeCreate, edit and delete webhooks and retry a delivery.POST /v1/webhooks
PATCH /v1/webhooks/{id}
DELETE /v1/webhooks/{id}
POST /v1/webhook-deliveries/{id}/retry
numbers:readSee your heysteff WhatsApp numbers and the plan quota.GET /v1/numbers
GET /v1/numbers/{id}
GET /v1/whatsapp-numbers/{id}
GET /v1/whatsapp-numbers/{id}/business-profile
numbers:writeReserve a number (with its connect link), release a reservation and request the display name.POST /v1/numbers
DELETE /v1/numbers/{id}
POST /v1/numbers/{id}/display-name
PATCH /v1/whatsapp-numbers/{id}/business-profile
flows:readSee your WhatsApp Flows, their Flow JSON, the preview and customers' answers.GET /v1/whatsapp-flows
GET /v1/whatsapp-flows/{id}
GET /v1/whatsapp-flows/{id}/json
GET /v1/whatsapp-flows/{id}/preview
GET /v1/whatsapp-flows/responses
flows:writeCreate, change, publish, deprecate and delete WhatsApp Flows, upload their Flow JSON and sync them with Meta.POST /v1/whatsapp-flows
POST /v1/whatsapp-flows/sync
PATCH /v1/whatsapp-flows/{id}
DELETE /v1/whatsapp-flows/{id}
PUT /v1/whatsapp-flows/{id}/json
POST /v1/whatsapp-flows/{id}/publish
POST /v1/whatsapp-flows/{id}/deprecate
calls:readSee the WhatsApp call log and a number's call settings.GET /v1/calls
GET /v1/whatsapp-numbers/{id}/calling
calls:writeTurn a number's calls on or off and change its hours.PATCH /v1/whatsapp-numbers/{id}/calling
inbox:embedCreate, see, change and revoke embedded inbox tokens.POST /v1/inbox-embeds
GET /v1/inbox-embeds
PATCH/DELETE /v1/inbox-embeds/{id}
logs:readRead the unified logs: API calls, webhook deliveries and failed messages (GET /v1/logs).
templates:writeCreate WhatsApp templates (they go to Meta for review) and delete them.POST /v1/templates
DELETE /v1/templates/{name}
customers:readSee your customers and the channels they connected.GET /v1/customers
GET /v1/customers/{id}
GET /v1/customers/{id}/channels
customers:writeCreate, change and delete customers, and generate their setup links.POST /v1/customers
PATCH /v1/customers/{id}
DELETE /v1/customers/{id}
POST /v1/customers/{id}/setup-links
agent:readSee the AI agent (on or off, model, trial quota, saved keys by their last 4 only) and its custom tools.GET /v1/agent
GET /v1/agent/tools
GET /v1/agent/tools/{id}
agent:writeConfigure the agent, save or delete your provider key and manage custom tools.PATCH /v1/agent
PUT /v1/agent/keys
DELETE /v1/agent/keys/{provider}
POST /v1/agent/tools
PATCH /v1/agent/tools/{id}
DELETE /v1/agent/tools/{id}
insights:readRead the findings from your conversations.GET /v1/insights

Rotate a key without downtime#

From the key list, Rotate creates a new secret and keeps the old one working for a grace period (24 hours by default). Deploy the new secret in that time; when the grace period ends, the old one stops working on its own.

IP allowlist#

You can restrict a key to a list of IPs or CIDR ranges (for example 203.0.113.0/24). A request from any other IP gets 403 even with a valid key.

Revoke#

Revoke kills the key immediately. Do it as soon as you suspect a leak, then create a new one for the integration.

Authentication errors#

StatusCodeWhat happened
401unauthorizedMissing header, or the key is invalid, expired or revoked.
403forbiddenThe key lacks the operation scope or the IP is not allowed.
403workspace_disabledThe workspace is disabled.
429rate_limitedYou went over the key rate limit.

Best practices#