This package allows you to track server-side customer events.
Base URL
The API host depends on the data region of your project:
Data region | API host |
|---|---|
EU (default) |
|
US |
|
https://api.gleap.io with your region's host. API tokens are per project and only valid in the project's region.Identify users
POST https://api.gleap.io/admin/identifyRequest headers:
Content-Type: application/json
Api-Token: YOUR_SECRET_API_TOKENPlease replace YOUR_SECRET_API_TOKEN with your project's identity verification secret, found in Settings → Security → User identity (the same secret that signs the user hash). Keep it on your server. The server API needs the Team plan or higher.
Request content:
{
"userId": "19283",
"name": "John Doe",
"email": "[email protected]",
"value": 1928,
"phone": "+1 (129) 18283 8292",
"createdAt": "2022-09-28T10:11:18.156Z",
"companyId": "acme-inc",
"companyName": "ACME inc.",
// You can also track custom user properties
}The optional value field is the contact's MRR: monthly recurring revenue, in your billing currency, in major units.
Set companyId to associate the user with a company. The optional companyName is a fallback label and never overwrites a name set authoritatively via the Companies endpoint (below).
Last activity update
By default the last activity gets updated to new Date(). You can prevent this by adding ?preventLastActivityUpdate=true to your request params.
POST https://api.gleap.io/admin/identify?preventLastActivityUpdate=trueMerge contacts
POST https://api.gleap.io/admin/contacts/mergeMerges contacts without a user ID (for example a contact created by an email to your support address, or a website visitor) into a user. Their conversations, messages and survey answers move to the user. Uses the same Api-Token header as above.
Request content:
{
"into": { "userId": "19283" },
"from": { "email": "[email protected]" }
}from.emailmerges every contact without a user ID that has this email.from.idmerges one contact by its Gleap ID instead.A contact that has its own user ID is never merged (400). An unknown user or contact answers 404.
Fields the user doesn't have yet (name, phone, company, custom data) are taken over from the merged contacts.
Response:
{ "merged": 2, "into": "6650f0..." }Companies
Create, update, read and delete companies. Companies hold authoritative attributes (plan, value, SLA, address and custom data) shown in the dashboard and used for company-level SLAs. All endpoints use the same Api-Token header as above.
Create or update a company
PUT https://api.gleap.io/admin/companies/{companyId}{companyId} is your own immutable identifier for the company (URL-encode it) — the same id you pass to identify as companyId. The company is created on first use and updated on subsequent calls.
Request headers:
Content-Type: application/json
Api-Token: YOUR_SECRET_API_TOKENRequest content:
{
"name": "ACME inc.",
"plan": "Growth plan",
"value": 4990,
"sla": 3600,
"domain": "acme.com",
"address": {
"line1": "1 Infinite Loop",
"city": "Cupertino",
"state": "CA",
"postalCode": "95014",
"country": "US"
},
"customData": {
"tier": "gold"
}
}sla is the response-time SLA in seconds. Unknown fields are ignored; companyId cannot be set from the body. Returns the saved company.
value is the company's MRR: monthly recurring revenue, in your billing currency, in major units. Kai Copilot weighs a company account with the maximum of the company value and its members' contact values, counted once per company. Update it from your billing webhooks; set 0 on cancellation.
Create or update many companies
POST https://api.gleap.io/admin/companies/bulkWrites up to 1000 companies in one call, for example a nightly sync from your customer database. Each entry is written exactly like the single PUT /admin/companies/{companyId} above, with companyId inside the entry. Send larger lists in several calls; re-sending entries is safe.
Request content:
{
"companies": [
{
"companyId": "LIZ123",
"name": "ACME inc.",
"plan": "Gold",
"sla": 3600,
"tags": ["kplus", "dms"],
"ownerEmail": "[email protected]",
"customData": {
"kplusVersion": "2026.2"
}
},
{
"companyId": "LIZ124",
"name": "Beta GmbH"
}
]
}Response:
{
"imported": 2,
"invalidRows": [],
"failed": []
}Entries with the same
companyIdare merged; the last one wins.invalidRowslists the positions (starting at 0) of entries without a usablecompanyId. Nothing is written for them.failedlists companies that could not be saved, with a message. Send them again.Unlike the single endpoint, a bulk write does not update the company's "last seen" time.
More than 1000 entries in one call answers
400.
Get a company
GET https://api.gleap.io/admin/companies/{companyId}Returns the company, or 404 if it does not exist.
Delete a company
DELETE https://api.gleap.io/admin/companies/{companyId}Permanently deletes the company. Its members (contacts) and their conversations are not deleted.
Pipelines (CRM)
Manage CRM pipeline entries from your backend: put a company or contact on a pipeline, move it through stages, set field values, or remove it. All endpoints use the same Api-Token header as above.
Entries are addressed by your own identifiers — the companyId you pass to the Companies endpoints for company pipelines, or the userId you pass to identify for contact pipelines (URL-encode both). Whether a pipeline holds companies or contacts is its recordType.
List pipelines
GET https://api.gleap.io/admin/pipelinesReturns every pipeline of the project with its stages and fields — everything needed for the entry endpoints below:
[
{
"id": "665f1c2e8b4d2a0012345678",
"name": "Onboarding",
"recordType": "COMPANY",
"stages": [{ "id": "stage-id", "name": "New", "color": "#6B7CFF" }],
"fields": [{ "fieldId": "dealsize", "label": "Deal size", "type": "CURRENCY", "currency": "USD" }]
}
]Stage ids are the same ids the v3 API calls laneId (a pipeline's lanes) — if you use both surfaces, they are interchangeable.
Add a record to a pipeline
POST https://api.gleap.io/admin/pipelines/{pipelineId}/companies/{companyId}
POST https://api.gleap.io/admin/pipelines/{pipelineId}/contacts/{userId}Request content (all fields optional):
{
"stageId": "stage-id",
"values": { "dealsize": 4990 }
}stageId defaults to the pipeline's first stage. values are keyed by fieldId; values must be primitives (string, number, boolean or null). Returns 201 with the created entry. Adding is idempotent: if the record is already on the pipeline, the existing entry is returned unchanged with 200 — use the PUT endpoint to also update an existing entry. A genuine add runs the pipeline's automations, exactly like the same action in the dashboard.
Create or update an entry
PUT https://api.gleap.io/admin/pipelines/{pipelineId}/companies/{companyId}
PUT https://api.gleap.io/admin/pipelines/{pipelineId}/contacts/{userId}Same body as above. If the record is not on the pipeline it is added; otherwise its entry is updated: stageId moves it (running the stage's automations), and values are merged — fields you do not send are left untouched, null clears a field.
Response:
{
"id": "665f1d4a8b4d2a0087654321",
"pipelineId": "665f1c2e8b4d2a0012345678",
"recordType": "COMPANY",
"companyId": "acme-inc",
"stageId": "stage-id",
"values": { "dealsize": 4990 },
"createdAt": "2026-08-12T09:00:00.000Z",
"updatedAt": "2026-08-12T09:00:00.000Z"
}Get an entry
GET https://api.gleap.io/admin/pipelines/{pipelineId}/companies/{companyId}
GET https://api.gleap.io/admin/pipelines/{pipelineId}/contacts/{userId}Returns the entry, or 404 if the record is not on the pipeline.
Remove an entry
DELETE https://api.gleap.io/admin/pipelines/{pipelineId}/companies/{companyId}
DELETE https://api.gleap.io/admin/pipelines/{pipelineId}/contacts/{userId}Removes the record from the pipeline. The company or contact itself is kept.
Errors
Unknown pipelines, records or entries return 404. An unknown stageId, an unknown values key or a non-primitive value returns 400 with a message naming the valid ids. Using a companies URL on a contact pipeline (or vice versa) returns 400 with the correct route.
Track events
POST https://api.gleap.io/admin/trackRequest headers:
Content-Type: application/json
Api-Token: YOUR_SECRET_API_TOKENRequest content:
{
"events": [{
"date": "2022-09-28T10:11:18.156Z",
"name": "Subscription started",
"data": {
"name": "Sub 1232",
"value": 1200
},
"userId": "19283"
}, {
"date": "2022-09-28T10:11:18.156Z",
"name": "Subscription canceled",
"data": {
"name": "Sub 1259",
"value": 1200,
"reason": "Stopped working on the project.",
},
"userId": "19283"
}]
}Rate limit
Please note that the identify and track APIs enforce a rate limit of 1500 requests / 60 seconds per API token. On the October 2026 plans this is the Team limit; Pro allows 4,500 and Enterprise 15,000 (see Plans and AI pricing). Starter has no API access (Team and up). If you exceed the limit, requests are rejected with 429 Too Many Requests and the token is blocked for a short period before requests are accepted again.

