Skip to content
Docs
API reference Go to dashboard
DocsAPI ReferenceAPI Keys

API Reference

The Alpheris API gives you programmatic access to your inbox, tickets, leads and contacts. This page covers the exact authentication model, how to manage your API keys, and a complete reference of every endpoint reachable via a key – including curl examples, sample responses and error codes.

!
The API is available only on Business and Enterprise. Current plan: Free. API key calls are rejected with 402 plan required as long as your shop is not on Business or Enterprise.

Requirements

  • Plan: Business or Enterprise. Other plans receive 402 plan required on API key calls.
  • Shop status: Your shop must be active. Inactive shops receive 403 shop_inactive.
  • API key: Created in the Dashboard (see below). The full key is shown only once – right when you create it.
  • Feature gates: Some endpoints additionally require a feature of your plan (e.g. inbox, tickets, contacts_basic). If the feature is missing, the server responds with 402.

Connect the API in 4 steps

  1. Create a key: in the Dashboard under /dashboard/api-keys.
  2. Store the key server-side: e.g. as an environment variable – never in the browser frontend.
  3. Authenticate the request: via Authorization: Bearer <key> (recommended) or X-API-Key: <key>.
  4. Verify with a test call: first GET /api/me, then the functional endpoints.

Authentication

Every API call is authenticated with a shop API key. The server reads the key from one of two headers – the Authorization header is checked first, then X-API-Key:

  • Authorization: Bearer <key>  (recommended)
  • X-API-Key: <key>

API keys carry the prefix sb_live_. The base URL of your integration is https://docs.alpheris.com. The same endpoint can alternatively be called through a logged-in Dashboard session (cookie instead of key) – but for external integrations, the API key is the only intended method.

bash
# Store the key server-side as an environment variable
export ALPHERIS_API_KEY="sb_live_xxxxxxxxxxxxxxxxxxxxxxxx"
export ALPHERIS_BASE_URL="https://docs.alpheris.com"

# Authenticated test call (recommended header)
curl -sS "$ALPHERIS_BASE_URL/api/me" \
  -H "Authorization: Bearer $ALPHERIS_API_KEY"

# Alternatively with X-API-Key
curl -sS "$ALPHERIS_BASE_URL/api/me" \
  -H "X-API-Key: $ALPHERIS_API_KEY"
python
import os, requests

base_url = "https://docs.alpheris.com"
api_key = os.environ["ALPHERIS_API_KEY"]  # sb_live_...

r = requests.get(
    f"{base_url}/api/me",
    headers={"Authorization": f"Bearer {api_key}"},
    timeout=20,
)
print(r.status_code, r.json())

Sample response: GET /api/me

Confirms authentication, shop, plan and the auth mode used (api_key or session).

json
{
  "user_id": 0,
  "email": "api@integration",
  "shop_id": 42,
  "shop_name": "My Shop",
  "plan": "business",
  "role": "integration",
  "auth_mode": "api_key",
  "acl": { }
}

Manage API keys

API keys are managed in the Dashboard under Dashboard → API Keys (/dashboard/api-keys). Management itself is only possible through a logged-in Dashboard session and with a Manager/Owner role – not via an API key. This requires an active shop on the Business or Enterprise plan.

ActionEndpoint (Session)Description
ListGET /api/inbox/integration-keysReturns all of the shop's keys with label, prefix, masked value, status and last use.
CreatePOST /api/inbox/integration-keysCreates a new key. Optional field label. The full key is returned only once, in this response.
RotatePOST /api/inbox/integration-key/rotateCreates a new primary key. The previous primary key is replaced.
RevokePOST /api/inbox/integration-keys/{key_id}/revokeSets a key to revoked. Revoked keys are rejected immediately.
!
The full key is visible only once. Right when you create or rotate it, the key is returned in plain text – after that Alpheris stores only a SHA-256 hash and the masked prefix (sb_live_xxxx…). If a key is lost, you have to revoke it and create a new one.

Note: The management endpoints above expect a Dashboard session (cookie) and cannot be called via an API key. In practice, managing them through the Dashboard page /dashboard/api-keys is enough.

Chat API (AI Replies)

With the Chat API you embed the Alpheris chatbot directly into your own website, app or backend – without our JS widget. You send a message, and Alpheris responds with an answer grounded in your real shop data (no hallucinating) plus the sources it used. Base URL: $ALPHERIS_BASE_URL/v1/…. Available on Enterprise, or on Business with the branding add-on – otherwise the Chat API returns 402 plan_required. The export below is available from Business.

POST /v1/chat

One message in – one complete answer out. The shop context comes from the key (don't send a shop_id). Omitting conversation_id starts a new conversation; sending the same value again continues the thread.

FieldTypeDescription
messagestring (required)The user message.
conversation_idstringOptional. Empty = new conversation; same value = continue the thread.
visitor_idstringOptional. A stable end-customer identifier from your site.
languagestringOptional. auto (default) or e.g. de, en.
bash
curl -sS -X POST "$ALPHERIS_BASE_URL/v1/chat" \
  -H "Authorization: Bearer $ALPHERIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "message": "How long does shipping to Austria take?" }'
json
{
  "reply": "Shipping to Austria usually takes 2-4 business days.",
  "conversation_id": "conv_ab12...",
  "message_id": "msg_00987",
  "sources": [
    { "url": "https://yourshop.com/faq/shipping", "title": "Shipping & delivery times", "snippet": "Delivery to AT: 2-4 business days ...", "type": "faq" }
  ],
  "confidence": 0.82,
  "plan": "business"
}
javascript
const res = await fetch(`${process.env.ALPHERIS_BASE_URL}/v1/chat`, {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.ALPHERIS_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ message: "Do you have this in size M?" }),
});
const data = await res.json();
console.log(data.reply, data.sources);

POST /v1/chat/stream

Like /v1/chat, but as Server-Sent Events (SSE): the answer arrives token by token for a live-typing feel. Each line is a data: {…} frame – token frames carry {"t":"…"}, the closing frame {"done":true, …} contains the full answer including sources.

bash
curl -sS -N -X POST "$ALPHERIS_BASE_URL/v1/chat/stream" \
  -H "Authorization: Bearer $ALPHERIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "message": "Are you available right now?" }'

# data: {"t": "Hey! Yes, "}
# data: {"t": "we're here ..."}
# data: {"done": true, "reply": "...", "conversation_id": "...", "sources": [...]}
!
Rate limit: 5 requests/second per API key. If you exceed it, the server responds with 429 plus Retry-After and X-RateLimit-* headers. Every chat turn counts against your message quota.

Data Export (transfer to another system)

Pull your data out of Alpheris programmatically – for a one-time migration or an ongoing sync into your CRM/helpdesk. Paginated via a cursor (no 500-item limit), so the entire history is reachable too. Business/Enterprise.

GET /v1/export/{entity}

{entity} is one of contacts, tickets, conversations, messages, leads. Query parameters: limit (1–1000, default 200), cursor (the next_cursor from the previous page), and for messages additionally the optional thread_id.

bash
curl -sS "$ALPHERIS_BASE_URL/v1/export/contacts?limit=200" \
  -H "Authorization: Bearer $ALPHERIS_API_KEY"
json
{
  "entity": "contacts",
  "data": [
    { "id": 51, "name": "Jane Example", "email": "[email protected]", "phone": "", "company": "", "tags": [], "created_at": 1718700000 }
  ],
  "count": 1,
  "next_cursor": 51,
  "has_more": false
}

Pagination: As long as has_more: true, repeat the next call with ?cursor=<next_cursor> until next_cursor: null comes back.

javascript
// Fetch all contacts page by page
let cursor = 0, all = [];
while (true) {
  const r = await fetch(`${process.env.ALPHERIS_BASE_URL}/v1/export/contacts?limit=500&cursor=${cursor}`, {
    headers: { "Authorization": `Bearer ${process.env.ALPHERIS_API_KEY}` },
  });
  const page = await r.json();
  all.push(...page.data);
  if (!page.has_more) break;
  cursor = page.next_cursor;
}
!
Note: messages also contains internal team notes (is_internal: true) – that's your own data; filter it out on import if needed. Legacy URLs with /api/v1/… work identically to /v1/….

Endpoint Reference

The following endpoints are reachable via an API key. All expect the authentication header (Authorization: Bearer or X-API-Key); POST endpoints with a body additionally expect Content-Type: application/json. The shop context is derived automatically from the key – you don't need to send a shop_id.

GET /api/me

Checks authentication and returns shop, plan and role context. The ideal first test call.

bash
curl -sS "$ALPHERIS_BASE_URL/api/me" \
  -H "Authorization: Bearer $ALPHERIS_API_KEY"

GET /api/inbox/tickets

Loads the shop's tickets (up to 500, newest first). Requires the tickets feature. Optional query parameter status (e.g. open, closed, all); an unknown value results in 400 invalid_status_filter.

bash
curl -sS "$ALPHERIS_BASE_URL/api/inbox/tickets?status=open" \
  -H "Authorization: Bearer $ALPHERIS_API_KEY"

GET /api/inbox/threads

Lists the shop's conversation threads (email, chat, social) – the central inbox view. Requires the inbox feature. Threads are tenant-isolated and returned only for your own shop. Useful query parameters: source (e.g. all, email, chat, instagram), thread_limit (10–300), message_limit (1–120), as well as fast=1 or minimal=1 for leaner responses.

bash
curl -sS "$ALPHERIS_BASE_URL/api/inbox/threads?source=all&thread_limit=50" \
  -H "Authorization: Bearer $ALPHERIS_API_KEY"
json
{
  "ok": true,
  "threads": [
    {
      "id": "abc123",
      "subject": "Question about order #1234",
      "channel": "email",
      "status": "open",
      "customer_name": "Jane Example",
      "customer_email": "[email protected]",
      "last_message": "When will my order ship?",
      "unread_count": 1,
      "updated_at": 1718700000
    }
  ]
}

POST /api/inbox/tickets

Creates a new ticket. Requires the tickets feature. The required field is subject (at least 3 characters).

FieldTypeDescription
subjectstring (required)Subject, ≥ 3 characters.
descriptionstringDescription / first message (up to 8000 characters).
customer_namestringCustomer name.
customer_emailstringCustomer email (validated).
channelstringChannel, default web.
prioritystringTicket priority.
tagsstring[] or stringUp to 25 tags.
assignee_user_idintegerOptional assignment to a team member.
bash
curl -sS -X POST "$ALPHERIS_BASE_URL/api/inbox/tickets" \
  -H "Authorization: Bearer $ALPHERIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "Delivery delayed",
    "description": "Order #1234 has not arrived yet.",
    "customer_email": "[email protected]",
    "priority": "high",
    "tags": ["shipping", "complaint"]
  }'

GET /api/inbox/leads

Loads captured leads. Requires the inbox feature. Optional query parameter limit (1–500, default 120).

bash
curl -sS "$ALPHERIS_BASE_URL/api/inbox/leads?limit=50" \
  -H "Authorization: Bearer $ALPHERIS_API_KEY"

POST /api/inbox/leads

Creates a new lead. Requires the inbox feature. If no source is provided, the server sets lead_form_manual.

bash
curl -sS -X POST "$ALPHERIS_BASE_URL/api/inbox/leads" \
  -H "Authorization: Bearer $ALPHERIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Jane Example",
    "email": "[email protected]",
    "source": "website_contact_form"
  }'

Additional lead actions (also the inbox feature): POST /api/inbox/leads/{lead_id}/close, POST /api/inbox/leads/{lead_id}/reopen and POST /api/inbox/leads/{lead_id}/delete.

GET /api/inbox/customers

Loads the shop's contacts/customers. Requires the contacts_basic feature.

bash
curl -sS "$ALPHERIS_BASE_URL/api/inbox/customers" \
  -H "Authorization: Bearer $ALPHERIS_API_KEY"
json
{
  "ok": true,
  "customers": [
    {
      "name": "Jane Example",
      "email": "[email protected]"
    }
  ]
}

POST /api/inbox/customers

Creates a contact. Requires the contacts_basic feature. The required field is a valid email; if it is missing, the server responds with 400 email_required.

FieldTypeDescription
emailstring (required)Valid email address.
namestringFull name (alternatively first_name + last_name).
phonestringPhone number.
companystringCompany.
notesstringNote (up to 4000 characters).
tagsstring[] or stringUp to 25 tags.
bash
curl -sS -X POST "$ALPHERIS_BASE_URL/api/inbox/customers" \
  -H "Authorization: Bearer $ALPHERIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "name": "John Example",
    "company": "Example Inc.",
    "tags": ["b2b", "newsletter"]
  }'

POST /api/inbox/threads/{conversation_id}/reply

Sends a reply into an existing conversation thread (e.g. an email conversation). For idempotent sending, always include a unique client_msg_id – that way retries on timeouts don't create duplicates (server-side dedup on re-sync).

FieldTypeDescription
textstring (required)Reply text. Empty text results in 400 empty_text.
client_msg_idstringUnique ID for idempotency/dedup (up to 128 characters).
ccstringOptional CC recipients (comma/semicolon separated).
bccstringOptional BCC recipients.
email_account_idintegerOptional sending email account.
bash
curl -sS -X POST "$ALPHERIS_BASE_URL/api/inbox/threads/abc123/reply" \
  -H "Authorization: Bearer $ALPHERIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Hi, we will get back to you directly.",
    "client_msg_id": "reply-2026-06-18-001"
  }'
json
{
  "ok": true,
  "provider": "outlook",
  "conversation_id": "abc123",
  "message": {
    "id": "sent:outlook:reply-2026-06-18-001",
    "sender": "agent",
    "type": "outgoing",
    "text": "Hi, we will get back to you directly.",
    "client_msg_id": "reply-2026-06-18-001"
  }
}

Additional thread actions via API key: POST /api/inbox/email/new (start a new email), POST /api/inbox/threads/{conversation_id}/assign (assign a thread), plus ticket status changes: POST /api/inbox/tickets/{ticket_id}/close, .../reopen and .../reroute.

POST /api/inbox/threads/{conversation_id}/close

Closes a conversation thread. Requires the inbox feature. It is reopened via .../reopen, and permanently deleted via .../delete. All three actions are tenant-isolated to your own shop.

bash
# Close
curl -sS -X POST "$ALPHERIS_BASE_URL/api/inbox/threads/abc123/close" \
  -H "Authorization: Bearer $ALPHERIS_API_KEY"

# Reopen
curl -sS -X POST "$ALPHERIS_BASE_URL/api/inbox/threads/abc123/reopen" \
  -H "Authorization: Bearer $ALPHERIS_API_KEY"

# Permanently delete
curl -sS -X POST "$ALPHERIS_BASE_URL/api/inbox/threads/abc123/delete" \
  -H "Authorization: Bearer $ALPHERIS_API_KEY"

POST /api/inbox/tickets/{ticket_id}/delete

Permanently deletes a ticket along with its associated messages. Requires the tickets feature. If the ticket does not exist in your own shop, the server responds with 404 ticket_not_found.

bash
curl -sS -X POST "$ALPHERIS_BASE_URL/api/inbox/tickets/42/delete" \
  -H "Authorization: Bearer $ALPHERIS_API_KEY"

DELETE /api/inbox/customers/{customer_id}

Permanently deletes a contact/customer. Requires the contacts_basic feature. If the contact does not exist in your own shop, the server responds with 404 customer_not_found.

bash
curl -sS -X DELETE "$ALPHERIS_BASE_URL/api/inbox/customers/7" \
  -H "Authorization: Bearer $ALPHERIS_API_KEY"

Error Codes

Authentication and plan gating follow a fixed scheme. Functional errors are additionally returned with 4xx and an error field in the JSON body.

Statusdetail / errorMeaning & action
401not authenticatedNeither session nor API key present. Set the Authorization: Bearer or X-API-Key header.
401invalid_api_keyThe key is unknown or has been revoked. Check for an active key in the Dashboard.
402plan requiredShop plan is not Business/Enterprise. Upgrade required.
402Feature '…' requires plan upgradeThe required feature (e.g. tickets, contacts_basic) is not included in the plan.
403shop_inactiveThe shop is not active. Clarify the account/subscription status.
400e.g. subject_required, email_requiredValidation error in the request body. Add the required fields.
404e.g. key_not_foundResource (e.g. thread/key) not found.
409e.g. key_not_activeConflict on the resource. Reload the object and try again.
5xx—Temporary server error. Retry with backoff and the same client_msg_id.
i
Important: Use API keys server-side only, never ship them in the browser frontend. Plan for regular key rotation and revoke unused keys. Every call updates last_used_at of the key – that's how you spot unused keys in the Dashboard.