#Quickstart in 5 Minutes
Status: server API (reading, wallet, webhooks) — Available; sandbox and test keys — Planned; widget and loader — Available. Steps 1–4 relate to the server API and describe the target behavior. Step 5 (the widget) works today.
Goal of this page: issue a key, choose your cell's address, verify access with a GET /me call, make a first useful request, and embed the chat with a single line.
#What you need
- A tenant account and an employee with the
integrations.managepermission (by default, the owner and the manager). - A license with the
api_accessflag (otherwise key issuance is unavailable and calls receivefeature_not_in_plan). - Knowing which cell your account is in: RU, EN, or ID. The cell is determined by the domain you use to sign in to the dashboard.
#Step 1. Issue a key
- Sign in to your cell's dashboard.
- Open Settings → API.
- Create an integration (a service account) and choose scopes.
analytics:readis enough for a first look. - Set the key name, the mode (
liveortest), and, if needed, a list of allowed IPs. - Copy the key. It is shown only once. A lost key cannot be recovered; you can only issue a new one.
A key looks like this (the example is deliberately fake):
sap_ru_live_EXAMPLE0KEYID_EXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLEX
Put the key in an environment variable or in your server's secret store:
export SAPPORT_API_KEY='sap_ru_live_EXAMPLE0KEYID_…'
For details, see Authentication.
Test keys (
sap_<cell>_test_…) work on the cell's sandbox. The sandbox is Planned.
#Step 2. Choose your cell's address
A key works only in the cell where it was issued.
| Cell | Base address |
|---|---|
| RU | https://formula-cream.pro/api/public/v1 |
| EN | https://wfacademy.org/api/public/v1 |
| ID | https://wfacademy.id/api/public/v1 |
export SAPPORT_BASE_URL='https://formula-cream.pro/api/public/v1'
An RU key used at the EN address returns 401 wrong_cell with a correct_base_url field containing the right address. See Cells and data.
#Step 3. Verify the key with GET /me
GET /me requires no scopes and costs nothing. It returns the tenant, the cell, the integration, key details (scopes, expiry, IP list), limits, the wallet state, and the CRM mode.
#curl
curl -sS "$SAPPORT_BASE_URL/me" \
-H "Authorization: Bearer $SAPPORT_API_KEY"
#JavaScript (Node.js 18+, fetch)
const res = await fetch(`${process.env.SAPPORT_BASE_URL}/me`, {
headers: { Authorization: `Bearer ${process.env.SAPPORT_API_KEY}` },
});
if (!res.ok) {
const problem = await res.json(); // application/problem+json
throw new Error(`${problem.code}: ${problem.detail} (request ${problem.request_id})`);
}
console.log(await res.json());
#Python (httpx)
import os
import httpx
resp = httpx.get(
f"{os.environ['SAPPORT_BASE_URL']}/me",
headers={"Authorization": f"Bearer {os.environ['SAPPORT_API_KEY']}"},
timeout=10,
)
if resp.status_code != 200:
problem = resp.json()
raise RuntimeError(f"{problem['code']}: {problem['detail']} (request {problem['request_id']})")
print(resp.json())
#PHP (cURL)
<?php
$ch = curl_init(getenv('SAPPORT_BASE_URL') . '/me');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('SAPPORT_API_KEY')],
CURLOPT_TIMEOUT => 10,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status !== 200) {
$problem = json_decode($body, true);
throw new RuntimeException($problem['code'] . ': ' . $problem['detail']);
}
print_r(json_decode($body, true));
#Example response
The values are illustrative; the structure is fixed.
{
"tenant": { "id": "3f0c9a52-0000-4000-8000-000000000001", "name": "Пример-студия" },
"cell": "ru",
"base_url": "https://formula-cream.pro/api/public/v1",
"integration": { "id": "int_EXAMPLE01", "name": "Моя CRM" },
"key": {
"key_id": "EXAMPLE0KEYID",
"mode": "live",
"scopes": ["analytics:read"],
"expires_at": "2027-10-11T00:00:00Z",
"ip_allowlist": []
},
"limits": {
"read_per_min": 600,
"write_per_min": 120,
"paid_per_min": 30,
"paid_concurrency": 5
},
"wallet": {
"balance": { "amount": "1500.00", "currency": "RUB" },
"state": "ok",
"exchange": "active",
"topup_url": "https://formula-cream.pro/ru/promo/economics#wallet",
"daily_spend": { "used": { "amount": "0.00", "currency": "RUB" }, "limit": { "amount": "500.00", "currency": "RUB" } }
},
"crm_mode": "internal",
"channel_id": "00000000-0000-4000-8000-000000000000"
}
The wallet.exchange field shows whether exchange is running: with suspended (a negative balance), the other routes respond with 402 wallet_suspended. See Wallet and exchange suspension.
The channel_id field is the identifier of the api channel created together with the integration; you need it if you run your own channel through the AI seller.
If you received a problem+json response instead, look up the code in the error catalog. The most common are invalid_api_key (a typo, or the key was revoked or expired), wrong_cell (the wrong address), or ip_not_allowed (a request from an address outside the list).
#Step 4. First useful call: traffic sources
Scope analytics:read, not paid, no personal data.
curl -sS "$SAPPORT_BASE_URL/analytics/traffic-sources?from=2026-10-01&to=2026-10-07" \
-H "Authorization: Bearer $SAPPORT_API_KEY"
Example response (illustrative):
{
"data": [
{ "source": "google", "kind": "search", "sessions": 1280, "visitors": 1104, "leads": 14 },
{ "source": "chatgpt", "kind": "ai_assistant", "sessions": 212, "visitors": 190, "leads": 5 },
{ "source": "social", "kind": "social", "sessions": 96, "visitors": 88, "leads": 1 }
],
"data_as_of": { "tracker": "2026-10-07" }
}
Note data_as_of: data from external sources (for example, the search console) arrives with a delay, and the platform reports honestly the point in time to which each source is current. Daily series are added with the include=series parameter. For parameters and metrics, see Reading analytics.
Other requests with the same key are in the README.
#Step 5. Connect the chat widget with one line
This already works. The widget does not need a secret key; it uses the public channel identifier.
- In the dashboard, create a "Web chat" channel and copy its identifier (a UUID).
- Paste this before
</body>on a page of your site:
<script src="https://formula-cream.pro/widget.js" data-channel="00000000-0000-4000-8000-000000000000"></script>
Replace the domain with your cell's domain (wfacademy.org for EN, wfacademy.id for ID) and the UUID with your own.
Optional parameters in the tag: data-position (bottom-right or bottom-left), data-theme (light by default), data-bubble-text, data-delay (seconds).
For the chat window to open, your site's domain must be listed in the tenant settings, or the site must be linked through a CMS module: the platform allows embedding only on such domains. Without this, the button is visible but the window is blocked by the browser.
For details, see Embedding the widget. If you also want analytics collection with one line, use the loader: Loader.
#What next
| I want to | Page |
|---|---|
| Understand keys, scopes, and rotation | Authentication |
| Know the error format, pagination, retries | Conventions |
| Receive events in real time | Webhooks |
| Run my own channel through the AI seller | Own channel |
| Connect an external CRM | CRM modes |