402 plan required as long as your shop is not on Business or Enterprise.
Requirements
- Plan: Business or Enterprise. Other plans receive
402 plan requiredon API key calls. - Shop status: Your shop must be
active. Inactive shops receive403 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 with402.
Connect the API in 4 steps
- Create a key: in the Dashboard under
/dashboard/api-keys. - Store the key server-side: e.g. as an environment variable – never in the browser frontend.
- Authenticate the request: via
Authorization: Bearer <key>(recommended) orX-API-Key: <key>. - 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.
# 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"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).
{
"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.
| Action | Endpoint (Session) | Description |
|---|---|---|
| List | GET /api/inbox/integration-keys | Returns all of the shop's keys with label, prefix, masked value, status and last use. |
| Create | POST /api/inbox/integration-keys | Creates a new key. Optional field label. The full key is returned only once, in this response. |
| Rotate | POST /api/inbox/integration-key/rotate | Creates a new primary key. The previous primary key is replaced. |
| Revoke | POST /api/inbox/integration-keys/{key_id}/revoke | Sets a key to revoked. Revoked keys are rejected immediately. |
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.
| Field | Type | Description |
|---|---|---|
message | string (required) | The user message. |
conversation_id | string | Optional. Empty = new conversation; same value = continue the thread. |
visitor_id | string | Optional. A stable end-customer identifier from your site. |
language | string | Optional. auto (default) or e.g. de, en. |
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?" }'{
"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"
}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.
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": [...]}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.
curl -sS "$ALPHERIS_BASE_URL/v1/export/contacts?limit=200" \
-H "Authorization: Bearer $ALPHERIS_API_KEY"{
"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.
// 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;
}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.
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.
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.
curl -sS "$ALPHERIS_BASE_URL/api/inbox/threads?source=all&thread_limit=50" \
-H "Authorization: Bearer $ALPHERIS_API_KEY"{
"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).
| Field | Type | Description |
|---|---|---|
subject | string (required) | Subject, ≥ 3 characters. |
description | string | Description / first message (up to 8000 characters). |
customer_name | string | Customer name. |
customer_email | string | Customer email (validated). |
channel | string | Channel, default web. |
priority | string | Ticket priority. |
tags | string[] or string | Up to 25 tags. |
assignee_user_id | integer | Optional assignment to a team member. |
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).
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.
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.
curl -sS "$ALPHERIS_BASE_URL/api/inbox/customers" \
-H "Authorization: Bearer $ALPHERIS_API_KEY"{
"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.
| Field | Type | Description |
|---|---|---|
email | string (required) | Valid email address. |
name | string | Full name (alternatively first_name + last_name). |
phone | string | Phone number. |
company | string | Company. |
notes | string | Note (up to 4000 characters). |
tags | string[] or string | Up to 25 tags. |
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).
| Field | Type | Description |
|---|---|---|
text | string (required) | Reply text. Empty text results in 400 empty_text. |
client_msg_id | string | Unique ID for idempotency/dedup (up to 128 characters). |
cc | string | Optional CC recipients (comma/semicolon separated). |
bcc | string | Optional BCC recipients. |
email_account_id | integer | Optional sending email account. |
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"
}'{
"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.
# 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.
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.
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.
| Status | detail / error | Meaning & action |
|---|---|---|
401 | not authenticated | Neither session nor API key present. Set the Authorization: Bearer or X-API-Key header. |
401 | invalid_api_key | The key is unknown or has been revoked. Check for an active key in the Dashboard. |
402 | plan required | Shop plan is not Business/Enterprise. Upgrade required. |
402 | Feature '…' requires plan upgrade | The required feature (e.g. tickets, contacts_basic) is not included in the plan. |
403 | shop_inactive | The shop is not active. Clarify the account/subscription status. |
400 | e.g. subject_required, email_required | Validation error in the request body. Add the required fields. |
404 | e.g. key_not_found | Resource (e.g. thread/key) not found. |
409 | e.g. key_not_active | Conflict on the resource. Reload the object and try again. |
5xx | — | Temporary server error. Retry with backoff and the same client_msg_id. |
last_used_at of the key – that's how you spot unused keys in the Dashboard.