Provider Integration & API Documentation
The technical contract for connecting any gaming platform or infrastructure to CoCrm.ai — a transport-agnostic definition of the data we ingest, the events we emit, and the widget we embed.
1Introduction
CoCrm.ai is an intelligent CRM and marketing‑automation platform for the iGaming industry. It ingests player, deposit, withdrawal and gameplay data, builds a unified player profile, and powers segmentation, journeys, loyalty programs, campaigns and real‑time messaging.
This document is the technical contract for integrating any external gaming platform (referred to throughout as the “Provider”) with CoCrm.ai. It is Provider‑agnostic: the same contract applies to every platform, sportsbook, casino aggregator or infrastructure vendor.
CoCrm.ai supports multiple ingestion transports — synchronous REST, message streaming (Kafka, RabbitMQ), realtime WebSocket, Redis Streams and batch file transfer — so a Provider can integrate using whatever its stack already speaks. All transports carry the same canonical record model (§17), so the choice of transport never changes the data contract. A client‑side widget (§16) adds Live Support (chat + click‑to‑call) on the Provider’s site and iGaming screens.
Push, don’t poll
Stream domain events to us as they occur. We upsert idempotently — re‑sending is always safe.
Transport-agnostic
One canonical record model over REST, Kafka, RabbitMQ, WebSocket, Redis or batch files.
Incremental
Start with one data type over one transport, then expand. No “big‑bang” migration required.
2Integration model
Integration is bidirectional and split into independent channels. A Provider may adopt any subset:
| # | Channel | Direction | Purpose |
|---|---|---|---|
| 1 | Data ingestion | Provider → CoCrm.ai | Stream/push casino & sport bets, deposits/withdrawals, player info, KYC, bonuses, transactions, category & balance updates. Multiple transports (§6). |
| 2 | Analytics / Conversion | Provider → CoCrm.ai | High‑throughput marketing attribution & funnel events with anonymous‑to‑known identity stitching. |
| 3 | Webhooks | CoCrm.ai → Provider | CoCrm.ai notifies the Provider’s backend of CRM/loyalty events (tier changes, cashback, missions, tournaments, …). |
| 4 | Player Data (read) | Provider → CoCrm.ai | Optional read access to a player’s event timeline and unified profile for embedding in a Provider UI. |
| 5 | Client‑side widget | Browser ↔ CoCrm.ai | A JavaScript snippet embedded on the Provider’s site / iGaming screen that runs Live Support (chat + click‑to‑call) and player‑facing screens. See §16. |
All traffic is encrypted in transit (TLS). Credentials are issued per Provider during onboarding (§22).
3Environments & base URL
Each Provider is provisioned a dedicated tenant on CoCrm.ai with its own endpoints. Always use the values supplied to you; examples below use placeholders.
| Environment | Base URL / broker (example) | Purpose |
|---|---|---|
| Sandbox | https://<partner>-sandbox.cocrm.ai | Integration & acceptance testing |
| Production | https://<partner>.cocrm.ai | Live traffic |
- REST:
POSTunder/api/...; JSON bodies (UTF‑8),Content-Type: application/json. - Streaming/broker connection details (Kafka bootstrap servers, AMQP URI, WebSocket URL, Redis endpoint, SFTP/bucket) are provisioned per tenant and per transport during onboarding.
4Authentication
4.1 API Key — primary (REST & analytics)
Every REST request must include the API key issued to your tenant:
X-API-Key: <will_be_provided_separately>
Content-Type: application/json
- Issued per Provider, shared via a secure channel during onboarding.
- Keep it server‑side only — never expose it in a browser, mobile app or public repository.
- A missing or invalid key returns
401 Unauthorized(resultCode: 1). - Compared in constant time; rotatable on request with an overlap window.
- Combine with IP allow‑listing for production (§19).
4.2 Transport credentials (streaming)
| Transport | Auth mechanism |
|---|---|
| Kafka | SASL/SCRAM (username+password) or mTLS, always over TLS |
| RabbitMQ | Username+password over TLS (amqps://), optional mTLS |
| WebSocket | X-API-Key (or token) presented in the connection handshake |
| Redis Streams | Password (ACL user) over TLS |
| Batch (SFTP) | SSH key or password; (object storage) scoped access key |
4.3 Bearer token — optional (user‑scoped read)
User‑scoped read endpoints (§15) accept a short‑lived JWT:
Authorization: Bearer <token>
Only relevant when embedding CoCrm.ai data in an authenticated operator UI. Not required for the core integration.
4.4 Widget public key (client‑side)
The client‑side widget (§16) is initialised with a public tenant id (data-tenant-id). It is safe to expose in the browser and is not the secret X-API-Key.
4.5 Webhook signature — outbound
Outbound webhooks are signed with HMAC‑SHA256 using your webhook secret and delivered in the X-CoCrm-Signature header. See §14.3.
5General conventions
| Topic | Convention |
|---|---|
| Transport security | TLS 1.2+ everywhere. Plain HTTP / plaintext brokers are rejected. |
| Format | JSON, UTF‑8, for message payloads and REST bodies. |
| Multi‑tenant | PartnerId in every record identifies the tenant/brand for multi‑brand Providers. |
| Timestamps | ISO‑8601 in UTC (e.g. 2026-07-01T09:32:10Z). |
| Amounts | Decimal numbers in major currency units (e.g. 250.00), not cents. Always send Currency. |
| Identifiers | ClientId = the Provider’s player identifier as mapped to CoCrm.ai. |
| Idempotency | Every record carries a stable business id (BetId, TransactionId, …). Re‑delivery is safe — CoCrm.ai upserts and never duplicates. Applies to all transports. |
| Ordering | Where ordering matters, key by ClientId (Kafka partition key / AMQP consistent routing) so a player’s events stay ordered. |
| Versioning | Additive changes are backward compatible; breaking changes ship under a new version with notice. |
6Event streaming & ingestion transports
CoCrm.ai accepts inbound data over several transports. All transports carry the same canonical record model (§17) — the choice affects delivery semantics and operational fit, never the data contract. Pick what your stack already speaks; mix transports per data type if useful (e.g. Kafka for high‑volume bets, REST for KYC).
| Transport | Pattern | Best for | Delivery | Availability |
|---|---|---|---|---|
| REST Data Push API (§7) | Request/response (HTTPS POST) | Most integrations; simplest to adopt | At‑least‑once (client retry) | Available (default) |
| Kafka (§8) | Durable log / stream | High‑throughput streaming, replay, ordering | At‑least‑once, ordered per partition | Enterprise — provisioned |
| RabbitMQ / AMQP (§9) | Message queue | Reliable async delivery, backpressure | At‑least‑once, consumer‑acked | Enterprise — provisioned |
| WebSocket stream (§10) | Persistent bi‑directional | Low‑latency realtime events | At‑least‑once (app‑level ack) | Available |
| Redis Streams (§11) | Lightweight stream | When you already run Redis | At‑least‑once, consumer‑group | On request |
| Batch / file (§12) | Bulk file transfer | Historical backfill, reconciliation | Batch (per file) | Available |
Choosing a transport
- Just want it working fast? → REST Data Push API (§7).
- High event volume / want replay & ordering? → Kafka (§8).
- Need reliable async decoupling with acks & DLQ? → RabbitMQ (§9).
- Sub‑second realtime UI/automations? → WebSocket (§10).
- Already all‑in on Redis? → Redis Streams (§11).
- Loading history / nightly reconciliation? → Batch (§12).
7Inbound — Data Push API (REST)
The default, simplest transport. The Provider POSTs records to CoCrm.ai as they occur. CoCrm.ai records them on the player’s timeline, updates the unified profile, and evaluates active journeys, segments and automations.
7.1 Connection details
| Item | Value |
|---|---|
| Base URL | https://<partner>.cocrm.ai (sandbox: https://<partner>-sandbox.cocrm.ai) |
| Path prefix | /api/push/ |
| Method | POST (all endpoints) |
| Content-Type | application/json |
| Auth header | X-API-Key: <provided_separately> |
7.2 Response format
All push endpoints return a standard envelope with a numeric resultCode.
// 200 OK — Success
{ "message": "Your operation has been successfully completed.", "resultCode": 0 }
// 401 Unauthorized — Invalid API Key
{ "message": "Unauthorized", "resultCode": 1 }
// 400 Bad Request — Partner Not Found
{ "message": "Partner not found", "resultCode": 3 }
See §21 for the full reference.
7.3 Request format
{
"PartnerId": 12345,
"data": [
{ /* one or more records — see §17 / per-endpoint schema */ }
]
}
PartnerId— tenant/brand id (multi‑tenant). Required.data— a single record object, or an array for batching.- Records are idempotent on their business id.
data[] fail validation, the valid ones are still accepted and upserted; the response resultCode stays 0 and a rejected array lists the failed business ids with a reason. Because ingestion is idempotent, you may safely re‑send the whole batch — accepted records are not duplicated.7.4 Endpoints
| # | Method | URL | Description |
|---|---|---|---|
| 1 | POST | /api/push/casino-bets | Casino bets |
| 2 | POST | /api/push/sport-bets | Sport bets |
| 3 | POST | /api/push/all-sport-bets | All sport bets |
| 4 | POST | /api/push/first-calculated-sport-bets | First calculated sport bets |
| 5 | POST | /api/push/deposit-withdrawal | Approved deposit / withdrawal |
| 6 | POST | /api/push/all-deposit-withdrawal | All deposit / withdrawal |
| 7 | POST | /api/push/failed-deposit-withdrawal | Failed deposit / withdrawal |
| 8 | POST | /api/push/player-info | Player personal information |
| 9 | POST | /api/push/kyc-data | KYC data transfer |
| 10 | POST | /api/push/finished-bonus | Finished bonus data transfer |
| 11 | POST | /api/push/transaction-data | Transaction data transfer |
| 12 | POST | /api/push/category-update | Category update data transfer |
| 13 | POST | /api/push/balance-update | Balance update data transfer |
| 14 | POST | /api/push/player-sessions | Login / logout & session events |
| 15 | POST | /api/push/player-presence | Online status / presence updates |
| 16 | POST | /api/push/consent-update | Communication consent / opt‑in‑out (§17.11) |
| 17 | POST | /api/push/rg-limits | Responsible‑gaming limits & self‑exclusion (§17.12) |
| 18 | POST | /api/push/bonus-data | Bonus grant / update (§17.5) |
| 19 | POST | /api/push/game-catalog | Game & provider reference data (§17.13) |
| 20 | POST | /api/push/player-attributes | Custom player attributes / tags (§17.14) |
7.5 curl example
curl -X POST https://<partner>.cocrm.ai/api/push/deposit-withdrawal \
-H "X-API-Key: $COCRM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"PartnerId": 12345,
"data": [
{ "TransactionId": "DP-77120", "ClientId": 84213, "Type": "deposit",
"Amount": 250.00, "Currency": "EUR", "Status": "approved",
"ProcessedAt": "2026-07-01T09:32:10Z" }
]
}'
Representative per‑endpoint payloads are given in §17; authoritative field schemas are supplied in the onboarding appendix.
8Inbound — Kafka
For high‑throughput event streaming with replay and per‑partition ordering. Enterprise — provisioned (§6).
8.1 Topology
Two models are supported; choose one at onboarding:
- A. CoCrm consumes from your cluster — you expose bootstrap servers + SASL/mTLS credentials; CoCrm runs a consumer group against your topics.
- B. You produce to CoCrm‑managed topics — CoCrm provisions topics + credentials on its managed cluster; you produce to them.
8.2 Topics
One topic per data type, namespaced per tenant:
cocrm.<partner>.casino-bets
cocrm.<partner>.sport-bets
cocrm.<partner>.deposit-withdrawal
cocrm.<partner>.player-info
cocrm.<partner>.kyc-data
cocrm.<partner>.balance-update
...
8.3 Message format
- Key:
ClientId(keeps a player’s events in one partition, preserving order). - Value: one canonical record as JSON (§17) — the same object you would place in the REST
data[]array.PartnerIdis included in the value. - Headers (optional):
event_type,schema_version,source_key.
{
"PartnerId": 12345,
"BetId": "CB-99381723",
"ClientId": 84213,
"GameProviderId": 7,
"BetAmount": 20.00,
"WinAmount": 0.00,
"Currency": "EUR",
"CreatedAt": "2026-07-01T09:32:10Z"
}
8.4 Semantics & security
- Delivery: at‑least‑once; CoCrm commits offsets after successful processing. De‑dup is by business id, so replays are safe.
- Serialization: JSON by default; Avro/Protobuf + Schema Registry on request.
- Security: TLS required; SASL/SCRAM or mTLS auth. Topic ACLs scoped to your tenant.
- Replay/backfill: supported by resetting the consumer group offset (model A) or re‑producing historical records (model B).
9Inbound — RabbitMQ (AMQP)
For reliable, decoupled async delivery with acknowledgements and dead‑lettering. Enterprise — provisioned (§6).
9.1 Topology
- Exchange: topic exchange
cocrm.ingest(durable). - Routing key: the data type, e.g.
push.casino-bets,push.deposit-withdrawal,push.kyc-data. - Queues: CoCrm binds durable queues per data type; a dead‑letter queue captures messages that fail processing repeatedly.
- Model: you publish to the exchange (CoCrm‑managed vhost), or CoCrm consumes from your broker — agreed at onboarding.
9.2 Message format
- Body: one canonical record as JSON (§17), UTF‑8.
- Properties:
content_type=application/json,message_id= business id (used for idempotency),timestamp, optionaltype= event type.
Exchange: cocrm.ingest (topic, durable)
Routing key: push.deposit-withdrawal
Body: { "PartnerId": 12345, "TransactionId": "DP-77120",
"ClientId": 84213, "Type": "deposit", "Amount": 250.00,
"Currency": "EUR", "Status": "approved",
"ProcessedAt": "2026-07-01T09:32:10Z" }
9.3 Semantics & security
- Delivery: at‑least‑once; CoCrm acks only after successful processing; failures are
nacked and dead‑lettered after retry. - Ordering: best‑effort; key by
ClientIdin the routing strategy if strict per‑player ordering is required. - Security:
amqps://(TLS) with username/password; optional mTLS. Vhost and permissions scoped to your tenant.
10Inbound — WebSocket stream
For low‑latency realtime delivery. Available (§6). Built on Socket.IO.
10.1 Connection
wss://<partner>.cocrm.ai/ingest
- Authenticate in the handshake with
X-API-Key(header) or an auth token. - Persistent, bi‑directional; auto‑reconnect with backoff on the client.
10.2 Emitting records
Emit an ingest event whose payload is the canonical envelope (§17):
socket.emit('ingest', {
type: 'deposit-withdrawal',
PartnerId: 12345,
data: {
TransactionId: 'DP-77120', ClientId: 84213, Type: 'deposit',
Amount: 250.00, Currency: 'EUR', Status: 'approved',
ProcessedAt: '2026-07-01T09:32:10Z'
}
});
- Ack: CoCrm responds with an application‑level ack
{ ok: true }(or an error). Re‑send on missing ack — idempotency on business id keeps it safe. - Best for realtime UI/automation triggers and online presence (
type: "player-presence", §17.10); for very high sustained volume prefer Kafka (§8).
11Inbound — Redis Streams
A lightweight streaming option when the Provider already operates Redis. On request (§6).
- CoCrm consumes via a consumer group (
XREADGROUP) from a per‑tenant stream key, e.g.cocrm:<partner>:ingest. - Entry fields:
type(data type),payload(canonical record JSON, §17). - Delivery: at‑least‑once; entries are
XACK‑ed after processing; the pending entries list (PEL) provides retry visibility. - Security: TLS + ACL user/password scoped to the tenant’s stream keys.
XADD cocrm:<partner>:ingest * type deposit-withdrawal payload '{"PartnerId":12345,...}'
12Inbound — Batch / file (SFTP · object storage)
For historical backfills and periodic reconciliation. Available (§6).
- Format: newline‑delimited JSON (NDJSON) preferred; CSV supported. One file per data type; optional gzip.
- Envelope: each line is one canonical record (§17), including
PartnerId. - Delivery: upload to the tenant’s SFTP path or object‑storage bucket (S3‑compatible). A
.manifest.jsonper batch lists file names, record counts and a checksum. - Naming:
<data-type>_<YYYYMMDD>_<seq>.ndjson.gz(e.g.deposit-withdrawal_20260701_001.ndjson.gz). - Idempotency: records are upserted on business id, so re‑processing a file is safe.
- Cadence: one‑off (backfill) or scheduled (e.g. hourly/daily); agreed at onboarding.
13Inbound — Analytics & Conversion API
A lightweight, high‑throughput endpoint for marketing attribution and funnel analytics with anonymous‑to‑known identity stitching. Use it for web/app touchpoints and conversions where you have an anonymous visitor id. Available.
X-API-Key: <provided_separately>
Content-Type: application/json
13.1 Allowed event types
page_view, click, register, ftd, deposit, wager,
campaign_sent, campaign_click, campaign_open
register, ftd, deposit and wager are treated as conversion events; the rest are touchpoints.
13.2 Request body
| Field | Type | Req | Description |
|---|---|---|---|
anon_id | string | ● | Anonymous visitor id (cookie / device id). |
user_id | int | ○ | Known player id once identified — enables identity stitching. |
event_type | enum | ● | One of the allowed types above. |
source / channel / campaign / btag | string | ○ | Attribution tags. |
url | string | ○ | Page URL. |
device_type / country | string | ○ | Device & ISO country code. |
metadata | object | ○ | { amount, currency, transaction_id, message }. |
13.3 Example
curl -X POST https://<partner>.cocrm.ai/api/v1/analytics/events/collect \
-H "X-API-Key: $COCRM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"anon_id": "a1b2c3d4", "user_id": 84213, "event_type": "ftd",
"btag": "aff_12", "channel": "web",
"metadata": { "amount": 250.00, "currency": "EUR", "transaction_id": "T-99381723" }
}'
{ "status": "accepted" } (queued, async).14Outbound — Webhooks
CoCrm.ai can push CRM and loyalty events to a Provider‑hosted HTTPS endpoint. You register one or more endpoints during onboarding (URL + shared secret + subscribed event types). Available.
14.1 Payload envelope
POST <your-endpoint>
Content-Type: application/json
X-CoCrm-Signature: sha256=<hex-digest>
User-Agent: CoCrm-Webhook/1.0
{ "event": "tier_up", "timestamp": "2026-07-01T09:32:10.123Z", "data": { "clientId": 84213 } }
14.2 Event catalog (loyalty & CRM)
| event | Fired when | Key data fields |
|---|---|---|
tier_up | Player moves up a loyalty tier | clientId, fromTier, toTier |
streak_milestone | Login/activity streak milestone reached | clientId, streakDays, bonusXp |
mission_complete | A mission is completed | clientId, missionId |
achievement_unlocked | An achievement is unlocked | clientId, achievementId |
tournament_winner | Player wins a tournament | clientId, tournamentId |
lootbox_grant | A lootbox is granted | clientId, lootboxId |
lootbox_open | A lootbox is opened | clientId, lootboxId |
cashback_paid | Cashback is paid out | clientId, amount |
Subscribe to specific events, or to * to receive all events (including future additions).
14.3 Signature verification (required)
Each request carries an HMAC‑SHA256 signature of the raw request body in the X-CoCrm-Signature header, keyed with your shared secret. Verify before trusting the payload. (HTTP header names are case‑insensitive.)
Node.js
const crypto = require('crypto');
function verify(rawBody, signatureHeader, secret) {
const expected =
'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
const a = Buffer.from(signatureHeader || '');
const b = Buffer.from(expected);
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
PHP
$expected = 'sha256=' . hash_hmac('sha256', $rawBody, $secret);
if (!hash_equals($expected, $_SERVER['HTTP_X_COCRM_SIGNATURE'] ?? '')) {
http_response_code(401);
exit;
}
Python
import hmac, hashlib
def verify(raw_body: bytes, signature_header: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature_header or "")
timestamp (ISO‑8601 UTC). Reject deliveries whose timestamp is outside a ±5 minute tolerance, and de‑duplicate on the data business id (deliveries are at‑least‑once). This prevents replay of a captured, still‑valid signature.14.4 Delivery guarantees & retries
- At‑least‑once; your endpoint must be idempotent.
- Acknowledge with any 2xx within 5 seconds.
- Non‑2xx/timeout → exponential backoff 1m → 5m → 15m → 1h → 6h, up to 5 attempts, then marked failed.
15Player data endpoints (read)
Optional read endpoints (Bearer token, §4.3):
/events— recent event timeline (default 50;limitconfigurable)./unified-profile— aggregated identity, financial summary, engagement and computed features.?refresh=1forces a recompute.
16Client‑side widget — Live Support & Screen
CoCrm.ai’s Live Support (chat + click‑to‑call) and player‑facing Screen experiences run through a small JavaScript widget that the Provider embeds on its site or iGaming screen. Without this snippet the chat launcher and screen features do not appear — it is the client‑side counterpart of the server integration.
The widget:
- renders the chat launcher and window (fully themable from the CoCrm panel);
- connects over WebSocket to the Provider’s CoCrm tenant for realtime messaging;
- supports click‑to‑call (LiveKit) and proactive triggers (exit‑intent, scroll, idle, time‑on‑page);
- loads its live configuration from the tenant, so appearance/behaviour can be changed centrally without editing the site.
16.1 Embed snippet
Place the snippet just before the closing </body> tag on every page (or in your global template / iGaming screen layout):
<script>
(function (w, d, s, l, i) {
w[l] = w[l] || [];
var f = d.getElementsByTagName(s)[0],
j = d.createElement(s);
j.async = true;
j.id = 'cocrm-widget-script';
j.src = 'https://<partner>.cocrm.ai/widget/widget.js?v=' + Date.now();
j.setAttribute('data-tenant-id', '<YOUR_TENANT_ID>');
j.setAttribute('data-api-url', 'https://<partner>.cocrm.ai');
f.parentNode.insertBefore(j, f);
})(window, document, 'script', '_cocrmWidget');
</script>
16.2 Script attributes
| Attribute | Req | Description |
|---|---|---|
data-tenant-id | ● | Public tenant identifier for your CoCrm brand. Provided at onboarding. Safe to expose client‑side. |
data-api-url | ● | Your CoCrm tenant base URL, e.g. https://<partner>.cocrm.ai. The widget loads its config, styles and WebSocket connection from here. |
data-debug | ○ | "true" to enable verbose console logging while integrating. |
id="cocrm-widget-script"must be kept — the widget reads its own attributes from this element.- The widget auto‑creates its own container; no extra markup is required.
- Config is fetched from
GET /api/widget-config/{tenantId}on your tenant, so colours, texts, position and triggers are managed centrally in the CoCrm panel.
16.3 Assets loaded by the widget
| Resource | Origin | Purpose |
|---|---|---|
widget.js, styles.css | https://<partner>.cocrm.ai (your tenant) | Widget runtime & styles |
| Realtime socket | wss://<partner>.cocrm.ai | Live chat messaging |
socket.io client | https://cdn.socket.io | WebSocket client library |
| LiveKit client | https://cdn.jsdelivr.net | Click‑to‑Call (optional; degrades gracefully if blocked) |
16.4 Content Security Policy (CSP)
If your site enforces a CSP, allow the CoCrm origins so the widget can load and connect. Minimum directives:
script-src 'self' https://<partner>.cocrm.ai https://cdn.socket.io https://cdn.jsdelivr.net;
style-src 'self' https://<partner>.cocrm.ai 'unsafe-inline';
connect-src 'self' https://<partner>.cocrm.ai wss://<partner>.cocrm.ai;
img-src 'self' https://<partner>.cocrm.ai data:;
Adjust to your policy; the key requirement is that your tenant origin (HTTPS + WSS) and the two CDNs are reachable.
16.5 iGaming Screen (server‑rendered pages)
On operator “Screen” pages the same widget is used, but the logged‑in player’s identity is passed at render time so conversations attach to the known player instead of an anonymous visitor:
data-tenant-idis your tenant id (in CoCrm deployments derived from thebusinessUnitIdof the screen).- A visitor/player identity (e.g.
screen_<ClientId>) is supplied so the chat is linked to the player’sClientId— no pre‑chat form is shown for known players.
The exact identity‑injection hook for your screen/template is agreed during onboarding. On anonymous public pages the widget falls back to a pre‑chat form (name / email / phone, configurable) to capture visitor details.
16.6 Single‑page apps (SPA)
The snippet initialises once on load and persists across client‑side navigation. No per‑route re‑injection is needed; the launcher stays mounted.
17Canonical model & field schema
Every transport carries the same record objects. A REST call wraps them in { PartnerId, data: [...] }; a Kafka/RabbitMQ/Redis message carries one record; a batch file carries one record per line. The record schema does not change.
Map your internal columns to the fields below once, at onboarding. Field names may follow your own reporting model — the semantics defined here are what matter.
Legend: ● required ○ optional (recommended where relevant). Types: string, int, number, datetime (ISO‑8601 UTC), enum, bool.
17.1 Player (identity & profile)
The anchor object. Everything else references a player by ClientId.
| Field | Type | Req | What we expect |
|---|---|---|---|
ClientId | int | ● | Provider’s unique player id. Stable for the lifetime of the account. |
Username | string | ○ | Login / display handle. |
Email | string | ○ | Primary email (email journeys & identity). |
Phone | string | ○ | E.164 format preferred (SMS/WhatsApp). |
FirstName / LastName | string | ○ | Personalisation tokens. |
BirthDate | date | ○ | YYYY-MM-DD. Age gating & birthday journeys. |
Gender | enum | ○ | male · female · other · unknown. |
Country | string | ○ | ISO‑3166 alpha‑2 (e.g. TR). |
City / Language | string | ○ | City; language ISO‑639‑1 (tr, en). |
TimeZone | string | ○ | IANA tz (e.g. Europe/Istanbul) — enables send‑time optimisation for campaigns. |
Address / PostalCode | string | ○ | Postal address details (optional). |
Currency | string | ○ | Account default currency, ISO‑4217. |
Btag / AffiliateId | string | ○ | Acquisition / affiliate attribution tag. |
Status | enum | ○ | active · passive · blocked · self_excluded · closed. |
VipLevel / CategoryName | string | ○ | Provider’s VIP tier / category label. |
IsTest | bool | ○ | Marks internal/test accounts so we can exclude them. |
RegisteredAt | datetime | ○ | Account creation timestamp. |
RegistrationIp | string | ○ | IP at registration (fraud/geo signals). |
RegistrationChannel | enum | ○ | web · mobile · app · affiliate · retail. |
LastLoginAt | datetime | ○ | Most recent login (inactivity/churn signals). |
FirstDepositAt / FirstDepositAmount | datetime · number | ○ | FTD marker & value. |
17.2 Deposit / Withdrawal (financial transactions)
The most valuable data type. Track the full lifecycle — send status transitions, not just successes.
| Field | Type | Req | What we expect |
|---|---|---|---|
TransactionId | string | ● | Unique id of this money movement (idempotency key). |
ClientId | int | ● | Player who owns the transaction. |
Type | enum | ● | deposit or withdrawal. |
Amount | number | ● | Requested amount, major units. |
FinalAmount | number | ○ | Net amount actually credited/debited after fees. |
Currency | string | ● | ISO‑4217. |
Status | enum | ● | pending · approved · rejected · failed · cancelled. |
Method / PaymentSystem | string | ○ | e.g. card, bank_transfer, crypto, provider name. |
IsFirstDeposit | bool | ○ | Flags the player’s FTD. |
FailReason | string | ○ | Reason for rejected/failed transactions. |
CreatedAt | datetime | ○ | When the transaction was requested. |
ProcessedAt | datetime | ● | When it reached its final status (event timestamp). |
17.3 Casino bet (gameplay)
| Field | Type | Req | What we expect |
|---|---|---|---|
BetId | string | ● | Unique bet / round id (idempotency key). |
ClientId | int | ● | Player who placed the bet. |
BetAmount | number | ● | Stake, major units. |
WinAmount | number | ● | Payout (0 for a loss). |
Currency | string | ● | ISO‑4217. |
GameProviderId / GameProvider | int · string | ○ | Game studio / aggregator. |
GameId / GameName | string | ○ | Specific game identifier & label. |
RoundId | string | ○ | Groups multiple actions in one round. |
Status | enum | ○ | settled · open · refunded. |
CreatedAt | datetime | ● | When the bet was placed. |
17.4 Sport bet (gameplay)
| Field | Type | Req | What we expect |
|---|---|---|---|
BetId | string | ● | Unique bet slip id (idempotency key). |
ClientId | int | ● | Player who placed the bet. |
BetAmount | number | ● | Stake, major units. |
WinAmount | number | ○ | Payout once settled (0 for a loss). |
Currency | string | ● | ISO‑4217. |
BetType | enum | ○ | single · multi · system. |
Selections | int | ○ | Number of legs on the slip. |
Odds | number | ○ | Total decimal odds. |
SportName / EventName | string | ○ | Sport & event/competition label. |
Status | enum | ● | pending · won · lost · void · cashout. |
CreatedAt | datetime | ● | When the bet was placed. |
CalculatedAt | datetime | ○ | When settled (key for the “first calculated” feed). |
17.5 Bonus
| Field | Type | Req | What we expect |
|---|---|---|---|
BonusId | string | ● | Unique bonus grant id (idempotency key). |
ClientId | int | ● | Player who received the bonus. |
BonusType / BonusName | string | ○ | e.g. welcome, freespin, cashback, loss_bonus, + display name. |
Amount | number | ● | Bonus value, major units. |
Currency | string | ○ | ISO‑4217. |
WageringRequirement / WageringCompleted | number | ○ | Rollover target and progress. |
Status | enum | ● | granted · active · completed · expired · cancelled. |
GrantedAt / FinishedAt | datetime | ○ | Grant & completion/expiry timestamps. |
17.6 KYC
| Field | Type | Req | What we expect |
|---|---|---|---|
ClientId | int | ● | Player being verified. |
KycStatus | enum | ● | pending · verified · rejected. |
DocumentType | enum | ○ | passport · id_card · driver_license · utility_bill. |
VerifiedAt | datetime | ○ | When status last changed. |
RejectionReason | string | ○ | Reason when rejected. |
17.7 Balance & Category snapshots
| Field | Type | Req | What we expect |
|---|---|---|---|
ClientId | int | ● | Player. |
Balance | number | ● | Current real‑money balance. |
BonusBalance / WithdrawableBalance | number | ○ | Bonus & withdrawable splits. |
CategoryId / CategoryName | int · string | ○ | VIP/segment category (for category-update). |
PreviousCategory | string | ○ | Prior category, to detect promotions/demotions. |
Currency | string | ○ | ISO‑4217. |
UpdatedAt | datetime | ● | Snapshot timestamp. |
17.8 Generic transaction ledger
For money movements that are not deposits/withdrawals (bets, wins, bonus credits, adjustments, corrections). Use when you want a full audit ledger on the timeline.
| Field | Type | Req | What we expect |
|---|---|---|---|
TransactionId | string | ● | Unique ledger id (idempotency key). |
ClientId | int | ● | Player. |
Type / Category | string | ● | e.g. bet, win, bonus, adjustment, correction. |
Amount | number | ● | Signed amount (negative = debit). |
Currency | string | ● | ISO‑4217. |
BalanceBefore / BalanceAfter | number | ○ | Running balance for reconciliation. |
Description | string | ○ | Free‑text note. |
CreatedAt | datetime | ● | Ledger timestamp. |
17.9 Player session / login event
Login, logout and failed‑login events. Powers “active now” journeys, security/fraud signals, session‑based automations and login‑streak loyalty.
| Field | Type | Req | What we expect |
|---|---|---|---|
SessionId | string | ● | Unique session id (idempotency key). Same id for the login and its matching logout. |
ClientId | int | ● | Player the session belongs to. |
EventType | enum | ● | login · logout · login_failed. |
LoginAt | datetime | ● | When the session started (or the attempt occurred). |
LogoutAt | datetime | ○ | When the session ended (for logout). |
DurationSeconds | int | ○ | Session length in seconds (at logout). |
LoginMethod | enum | ○ | password · otp · social · sso · biometric. |
IsSuccessful | bool | ○ | false for login_failed. |
FailReason | string | ○ | Reason for a failed login (e.g. bad_password, locked, 2fa_failed). |
Ip | string | ○ | Client IP (geo & fraud signals). |
Country / City | string | ○ | ISO‑3166 alpha‑2 country; city name. |
DeviceType | enum | ○ | desktop · mobile · tablet · app. |
Os / Browser / AppVersion | string | ○ | Client environment details. |
CreatedAt | datetime | ● | Event timestamp. |
17.10 Online status / presence
The player’s real‑time online state. Powers “online right now” segments, live‑ops triggers and click‑to‑engage from the CRM. Presence is latest‑wins per ClientId (a new snapshot overwrites the previous state).
| Field | Type | Req | What we expect |
|---|---|---|---|
ClientId | int | ● | Player whose presence changed. |
Status | enum | ● | online · offline · away · in_game. |
IsOnline | bool | ○ | Convenience flag (true unless offline). |
LastSeenAt | datetime | ● | Timestamp of the last activity / heartbeat. |
SessionId | string | ○ | Current session (links presence to §17.9). |
Channel | enum | ○ | web · mobile · app. |
CurrentGameId / CurrentGameName | string | ○ | Active game when in_game. |
UpdatedAt | datetime | ● | Snapshot timestamp (used to resolve latest state). |
type: "player-presence" for realtime. The REST endpoint /api/push/player-presence is fine for periodic snapshots or heartbeats (e.g. every 30–60s). Send an offline event on disconnect so state doesn’t go stale.17.11 Communication consent (opt‑in / opt‑out)
Per‑channel marketing permissions. Required for CoCrm to legally message a player — without an opt‑in on a channel, campaigns on that channel are suppressed. Consent is latest‑wins per ClientId; send an update whenever the player changes a preference.
| Field | Type | Req | What we expect |
|---|---|---|---|
ClientId | int | ● | Player whose consent changed. |
EmailConsent | bool | ○ | Marketing email opt‑in. |
SmsConsent | bool | ○ | Marketing SMS opt‑in. |
PushConsent | bool | ○ | Push notification opt‑in. |
WhatsAppConsent | bool | ○ | WhatsApp opt‑in. |
PhoneConsent | bool | ○ | Outbound call / tele‑sales opt‑in. |
MarketingConsent | bool | ○ | Global marketing consent (overrides all channels when false). |
ConsentSource | string | ○ | Where captured: registration, preferences_page, support, … |
ConsentVersion | string | ○ | Terms/privacy version the player agreed to (audit trail). |
UpdatedAt | datetime | ● | When the preference last changed. |
false, that channel is treated as opted‑out and no marketing is sent on it (transactional messages excepted).17.12 Responsible Gaming — limits & self‑exclusion
Player‑protection state. CoCrm uses this to suppress marketing to self‑excluded / cooling‑off players and to power RG journeys. Latest‑wins per ClientId.
| Field | Type | Req | What we expect |
|---|---|---|---|
ClientId | int | ● | Player. |
SelfExcluded | bool | ○ | Currently self‑excluded. |
SelfExclusionStart / SelfExclusionEnd | datetime | ○ | Exclusion window (End null = permanent). |
CoolingOffUntil | datetime | ○ | Temporary time‑out end. |
DepositLimit / DepositLimitPeriod | number · enum | ○ | Amount + daily · weekly · monthly. |
LossLimit / LossLimitPeriod | number · enum | ○ | Net‑loss cap + period. |
WagerLimit / WagerLimitPeriod | number · enum | ○ | Stake cap + period. |
SessionTimeLimitMinutes | int | ○ | Max session length. |
RealityCheckMinutes | int | ○ | Reality‑check interval. |
Currency | string | ○ | Currency for money limits, ISO‑4217. |
UpdatedAt | datetime | ● | When limits/exclusion last changed. |
17.13 Game & provider catalog (reference data)
Reference data that lets CoCrm resolve GameId / GameProviderId from bets into readable names and categories for segmentation and reporting. Low frequency — Batch (§12) is a good fit.
| Field | Type | Req | What we expect |
|---|---|---|---|
GameId | string | ● | Unique game identifier (idempotency key). |
GameName | string | ● | Display name. |
GameProviderId / GameProvider | int · string | ○ | Studio / aggregator id & name. |
Category / SubCategory | string | ○ | e.g. slots, live_casino, table, crash, sportsbook. |
Volatility | enum | ○ | low · medium · high. |
Rtp | number | ○ | Return‑to‑player % (e.g. 96.5). |
IsActive | bool | ○ | Whether the game is live in the lobby. |
UpdatedAt | datetime | ○ | Catalog record timestamp. |
17.14 Custom player attributes & tags
A flexible escape hatch for provider‑specific signals CoCrm doesn’t model natively. Keys are agreed at onboarding and become available in segmentation. Latest‑wins per ClientId.
| Field | Type | Req | What we expect |
|---|---|---|---|
ClientId | int | ● | Player. |
Attributes | object | ○ | Key/value map, e.g. { "favorite_sport": "football", "risk_score": 72 }. |
Tags | string[] | ○ | Label list, e.g. ["vip_watch", "reactivation"]. |
UpdatedAt | datetime | ● | Snapshot timestamp. |
17.15 Representative JSON payloads
Casino bet
{ "PartnerId": 12345, "BetId": "CB-99381723", "ClientId": 84213,
"GameProviderId": 7, "GameId": "book-of-x", "BetAmount": 20.00,
"WinAmount": 0.00, "Currency": "EUR", "CreatedAt": "2026-07-01T09:32:10Z" }
Sport bet
{ "PartnerId": 12345, "BetId": "SB-55120033", "ClientId": 84213,
"BetAmount": 50.00, "WinAmount": 120.00, "Currency": "EUR",
"Selections": 3, "Status": "won", "CreatedAt": "2026-07-01T10:05:00Z" }
Deposit / withdrawal
{ "PartnerId": 12345, "TransactionId": "DP-77120", "ClientId": 84213,
"Type": "deposit", "Amount": 250.00, "Currency": "EUR", "Method": "card",
"Status": "approved", "ProcessedAt": "2026-07-01T09:32:10Z" }
Player info
{ "PartnerId": 12345, "ClientId": 84213, "Username": "player_84213",
"Email": "[email protected]", "Phone": "+90...", "FirstName": "…",
"LastName": "…", "BirthDate": "1990-05-14", "Country": "TR",
"Currency": "EUR", "RegisteredAt": "2025-11-02T08:00:00Z" }
KYC
{ "PartnerId": 12345, "ClientId": 84213, "KycStatus": "verified",
"DocumentType": "passport", "VerifiedAt": "2026-06-20T14:11:00Z" }
Balance update
{ "PartnerId": 12345, "ClientId": 84213, "Balance": 430.50,
"BonusBalance": 25.00, "Currency": "EUR", "UpdatedAt": "2026-07-01T09:40:00Z" }
Player session (login)
{ "PartnerId": 12345, "SessionId": "S-4471902", "ClientId": 84213,
"EventType": "login", "LoginAt": "2026-07-01T09:30:00Z", "LoginMethod": "password",
"IsSuccessful": true, "Ip": "203.0.113.42", "Country": "TR", "DeviceType": "mobile",
"CreatedAt": "2026-07-01T09:30:00Z" }
Online presence
{ "PartnerId": 12345, "ClientId": 84213, "Status": "in_game",
"IsOnline": true, "SessionId": "S-4471902", "Channel": "mobile",
"CurrentGameId": "book-of-x", "LastSeenAt": "2026-07-01T09:41:20Z",
"UpdatedAt": "2026-07-01T09:41:20Z" }
Communication consent
{ "PartnerId": 12345, "ClientId": 84213, "EmailConsent": true,
"SmsConsent": false, "PushConsent": true, "WhatsAppConsent": true,
"ConsentSource": "preferences_page", "ConsentVersion": "2026-05",
"UpdatedAt": "2026-07-01T09:20:00Z" }
Responsible‑gaming limits
{ "PartnerId": 12345, "ClientId": 84213, "SelfExcluded": false,
"DepositLimit": 1000.00, "DepositLimitPeriod": "monthly",
"SessionTimeLimitMinutes": 120, "Currency": "EUR",
"UpdatedAt": "2026-07-01T09:00:00Z" }
Custom attributes
{ "PartnerId": 12345, "ClientId": 84213,
"Attributes": { "favorite_sport": "football", "risk_score": 72 },
"Tags": [ "vip_watch", "reactivation" ], "UpdatedAt": "2026-07-01T09:15:00Z" }
The remaining types (all-sport-bets, first-calculated-sport-bets, all-deposit-withdrawal, failed-deposit-withdrawal, finished-bonus, transaction-data, category-update) follow the same conventions; fields are in the onboarding appendix.
18Data dictionary
| Field | Type | Notes |
|---|---|---|
PartnerId | int | Tenant / brand identifier for multi‑brand Providers. |
ClientId / clientId | int | Player identity mapped between Provider and CoCrm.ai. |
anon_id | string | Anonymous visitor identity for pre‑login analytics. |
TransactionId / BetId | string | Business id used for idempotent upserts. |
Amount / amount | number | Major currency units. Pair with Currency. |
Currency | string | ISO‑4217 (e.g. EUR, TRY, USD). |
Type | enum | e.g. deposit, withdrawal. |
Status | enum | e.g. approved, failed, won, lost. |
KycStatus | enum | e.g. pending, verified, rejected. |
SessionId | string | Login/session identifier; links session (§17.9) & presence (§17.10). |
EventType | enum | Session event: login, logout, login_failed. |
IsOnline / presence Status | bool · enum | Presence: online, offline, away, in_game. |
LastSeenAt | datetime | Last activity / heartbeat for presence. |
EmailConsent / SmsConsent / PushConsent / WhatsAppConsent | bool | Per‑channel marketing opt‑in (§17.11). |
SelfExcluded | bool | Responsible‑gaming self‑exclusion (§17.12). |
DepositLimit / LossLimit / WagerLimit | number | RG limits; pair with a *Period (daily/weekly/monthly). |
RegistrationIp | string | IP captured at registration (fraud/geo). |
TimeZone | string | IANA timezone for send‑time optimisation. |
Attributes / Tags | object · string[] | Custom provider signals for segmentation (§17.14). |
CreatedAt / ProcessedAt / UpdatedAt | datetime | ISO‑8601 UTC. |
data / payload | object/array | Record(s) — single object or array. |
19Security & compliance
- Transport: TLS 1.2+ for REST, brokers (Kafka/AMQP/Redis), WebSocket and SFTP.
- IP allow‑listing: provide your server IP addresses for whitelisting on the production tenant (REST + brokers).
- API key & broker credentials: issued per Provider, shared via a secure channel, rotatable on request; keep them server‑side only.
- Widget key: the client‑side
data-tenant-idis public by design and is not the secretX-API-Key— never place the secret key in browser code. - Webhook signing: all outbound webhooks are HMAC‑SHA256 signed — verify before trust.
- Multi‑tenant isolation:
PartnerIdscopes every record; topic/queue/stream ACLs are scoped per tenant. - Least privilege: credentials grant access only to the endpoints/topics in this document.
- Data minimisation: send only the fields required; avoid sensitive PII in free‑form fields unless contractually agreed.
20Rate limits & quotas
| Endpoint / transport | Default limit |
|---|---|
REST Data Push API (/api/push/*) | Provisioned per Provider by expected volume; batch large loads. |
Analytics collect (/api/v1/analytics/events/collect) | 30 requests / minute per key |
| Kafka / RabbitMQ / Redis Streams | Throughput sized per integration (partitions/prefetch) at onboarding. |
- REST over‑limit returns
429 Too Many Requests— back off and retry. - Every REST response carries rate‑limit headers:
X-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-Reset(epoch seconds). A429also includesRetry-After(seconds) — honour it before retrying. - Coordinate historical backfills (any transport) with the technical team.
21Errors & result codes
21.1 REST result codes
| resultCode | HTTP | Meaning |
|---|---|---|
0 | 200 | Success — operation completed. |
1 | 401 | Unauthorized — invalid or missing API key. |
3 | 400 | Partner not found — unknown/mismatched PartnerId. |
Treat any non‑0 resultCode as failure and inspect message.
21.2 HTTP status reference
| HTTP | Meaning | Notes |
|---|---|---|
200 | OK | Push endpoints return { resultCode, message }. |
202 | Accepted | Analytics events queued for async processing. |
400 | Bad Request | Validation failed / malformed body / partner not found. |
401 | Unauthorized | Invalid API key, or invalid webhook signature (receiver side). |
403 | Forbidden | IP not allow‑listed. |
429 | Too Many Requests | Rate limit exceeded — back off. |
5xx | Server Error | Transient — safe to retry the same idempotent record. |
21.3 Streaming failures
- Kafka: processing failures are retried; offsets commit only on success. Poison messages route to a dead‑letter topic after max retries.
- RabbitMQ: failed messages are
nacked and dead‑lettered after retry. - Redis Streams / WebSocket / Batch: unprocessed entries remain visible (PEL / missing ack / next file run) and are retried; idempotency prevents duplicates.
22Onboarding checklist
The CoCrm technical team will provision and agree the following with the Provider:
- Environments — sandbox + production base URLs / broker endpoints.
- Transport(s) — which of REST, Kafka, RabbitMQ, WebSocket, Redis Streams, Batch you will use, and for which data types.
- Credentials —
X-API-Keyand/or broker credentials (SASL/mTLS, AMQP user, Redis ACL, SFTP key), shared via a secure channel. - IP allow‑list — the Provider’s server IP addresses.
- PartnerId(s) — tenant/brand identifiers for multi‑brand setups.
- Identity mapping — how
ClientIdmaps between the Provider’s players and CoCrm.ai. - Data coverage — which record types you will send (start minimal, expand).
- Field schemas — the authoritative per‑type field appendix.
- Widget — tenant id + where the snippet is embedded (site / screen), and the player‑identity injection hook for authenticated pages (§16).
- Webhooks (optional) — endpoint URL(s), shared secret, subscribed events.
- Historical backfill (optional) — volume, transport & schedule.
Recommended rollout
- Connect in sandbox over your chosen transport; send a handful of test records.
- Embed the widget on a staging page and confirm Live Support connects.
- Verify records land on CoCrm.ai and enable webhooks if used (confirm signature).
- Run an acceptance check against a sample of real players.
- Switch to production credentials and go live incrementally, adding transports as needed.
23Platform requirements — collected from the Operator
The items below are provided by the Operator (the brand/business running the site), not the technical Provider. Where the Operator and Provider are the same company, one team may supply both. Please complete and submit the following during onboarding.
23.1 Domain requirements
Register the following domains with your domain registrar. CoCrm.ai will supply the DNS records (CNAME/A) and handle SSL once they are pointed. Replace yourbrand with your brand name.
| Domain | Purpose |
|---|---|
yourbrand-bonus.com | Player bonus request system |
yourbrand-partner.com | Affiliate partner login system |
yourbrand-link.com | Partner referral links |
yourbrand-cdn.com | File management, pop‑up images, static content hosting |
yourbrand-help.com | RAG Knowledge Base hosting |
23.2 Promotion & bonus configuration
Submit the following so CoCrm.ai can configure your promotion & bonus automation:
- Promotion rules document — a document (Word/PDF) detailing your promotion rules: the request → approval → automation flow.
- Bonus details document — the bonuses you want managed via automation (type, trigger conditions, amount/percentage, wagering, validity, eligibility).
- Bonus Engine configuration — the bonus configurations and rules exported from your infrastructure/provider panel.
24Support & versioning
- Contact: CoCrm Technical Team — [email protected]
- Versioning: additive changes (new fields, endpoints, transports) are backward compatible. Breaking changes ship under a new version with advance notice.
24.1 Changelog
| Version | Highlights |
|---|---|
| 1.4 | Added player session/login (§17.9), online presence (§17.10), communication consent (§17.11), responsible‑gaming limits & self‑exclusion (§17.12), game catalog (§17.13) and custom attributes (§17.14); new Player fields (RegistrationIp, TimeZone, RegistrationChannel, Address); bonus grant endpoint; Operator platform requirements — domains & promotion/bonus config (§23); partial‑batch, webhook‑replay & rate‑limit‑header clarifications. |
| 1.3 | Added streaming transports (Kafka, RabbitMQ, WebSocket, Redis Streams, Batch); client‑side Live Support widget (§16); consolidated canonical model & field schema (§17). |
| 1.2 | Generic “data we expect” model with per‑field schema; Analytics/Conversion API; webhook signature reference. |
| 1.0 – 1.1 | Initial Data Push API and Provider Integration Guide. |