MENU navbar-image

Introduction

Read/write client identity records and pull real, AI-verified WhatsApp check-in adherence data into your own CRM or backend system. Enterprise plan required.

This documentation aims to provide all the information you need to work with our API.

<aside>As you scroll, you'll see code examples for working with the API in different programming languages in the dark area to the right (or as part of the content on mobile).
You can switch the language used with the tabs at the top right (or from the nav menu at the top left on mobile).</aside>

Authenticating requests

To authenticate requests, include an Authorization header with the value "Bearer {YOUR_API_TOKEN}".

All authenticated endpoints are marked with a requires authentication badge in the documentation below.

Generate a token from Settings → Partner API Tokens (Enterprise plan required). Grant it the abilities it needs: clients:write to create/update client identity records, checkins:read to pull adherence data. The plaintext token is shown once at creation — store it securely.

Adherence

Real, AI-verified check-in adherence data — the core value of this API. Derived entirely from actual WhatsApp check-in behavior run through ZoetiCoach's own verification pipeline. This is deliberately read-only: there is no way to write a check-in through this API.

Get a client's adherence history

requires authentication

Per-day done/partial/missed/frozen/replied/none status for the requested window, plus the client's current streak and total points.

Example request:
curl --request GET \
    --get "https://zoeticoach.com/api/partner/v1/clients/client-8821/checkins?days=30" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://zoeticoach.com/api/partner/v1/clients/client-8821/checkins"
);

const params = {
    "days": "30",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "external_id": "client-8821",
    "days": [
        {
            "date": "2026-09-28",
            "status": "done"
        },
        {
            "date": "2026-09-29",
            "status": "partial"
        }
    ],
    "current_streak_days": 4,
    "total_points": 55,
    "week_energy_score": 7
}
 

Example response (404):


{
    "message": "Client not found."
}
 

Request      

GET api/partner/v1/clients/{externalId}/checkins

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

externalId   string     

Your own record id for this client. Example: client-8821

Query Parameters

days   integer  optional    

How many trailing days of history to return (1-90). Defaults to 30. Example: 30

Authentication

Introspect the current API token — its abilities and when it was created. Useful for a partner's SDK to confirm which endpoints a given token can call without having to trigger a 403 first.

Get the current token's abilities

requires authentication

Example request:
curl --request GET \
    --get "https://zoeticoach.com/api/partner/v1/me" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://zoeticoach.com/api/partner/v1/me"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "token_name": "Zapier integration",
    "abilities": [
        "clients:write",
        "checkins:read"
    ],
    "created_at": "2026-09-29T10:00:00.000000Z"
}
 

Request      

GET api/partner/v1/me

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Clients

Minimal client-identity endpoints — establishing the external_id mapping a partner needs to later pull adherence data via the Adherence group below. There is no list/enumerate endpoint anywhere in this API by design — every lookup requires you to already know the specific external_id you're asking about.

Create a client

requires authentication

Creates a minimal client-identity record and returns ZoetiCoach's own id alongside your external_id, so you can map the two going forward. Consent is never set via this API — the client starts inert (no WhatsApp check-ins) until they complete ZoetiCoach's own opt-in flow, which this call triggers automatically.

Send an Idempotency-Key header to make a retry of this exact request safe — a repeat with the same key returns the original response instead of creating a duplicate client.

Example request:
curl --request POST \
    "https://zoeticoach.com/api/partner/v1/clients" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"external_id\": \"client-8821\",
    \"name\": \"Priya Nair\",
    \"phone\": \"+919800011111\",
    \"language\": \"en\"
}"
const url = new URL(
    "https://zoeticoach.com/api/partner/v1/clients"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "external_id": "client-8821",
    "name": "Priya Nair",
    "phone": "+919800011111",
    "language": "en"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (201):


{
    "id": 42,
    "external_id": "client-8821",
    "name": "Priya Nair",
    "status": "active",
    "language": "en"
}
 

Example response (422):


{
    "message": "The external id has already been taken.",
    "errors": {
        "external_id": [
            "The external id has already been taken."
        ]
    }
}
 

Request      

POST api/partner/v1/clients

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Body Parameters

external_id   string     

The partner's own unique identifier for this client, used to look it up on every later call. Example: client-8821

name   string     

Client's full name. Example: Priya Nair

phone   string     

Client's WhatsApp number in E.164 format. Check-ins can't be dispatched without one. Example: +919800011111

language   string  optional    

Client's language for WhatsApp check-ins and AI chat: en, hi, or hinglish. Defaults to en. Example: en

Get a client

requires authentication

Look up a client by the external_id you gave it at creation.

Example request:
curl --request GET \
    --get "https://zoeticoach.com/api/partner/v1/clients/client-8821" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://zoeticoach.com/api/partner/v1/clients/client-8821"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "id": 42,
    "external_id": "client-8821",
    "name": "Priya Nair",
    "status": "active",
    "language": "en"
}
 

Example response (404):


{
    "message": "Client not found."
}
 

Request      

GET api/partner/v1/clients/{externalId}

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

externalId   string     

Your own record id for this client. Example: client-8821

Update a client

requires authentication

Updates name and/or status only — nothing else about a client is writable through this API.

Example request:
curl --request PATCH \
    "https://zoeticoach.com/api/partner/v1/clients/client-8821" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"name\": \"Priya Sharma\",
    \"status\": \"paused\"
}"
const url = new URL(
    "https://zoeticoach.com/api/partner/v1/clients/client-8821"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "name": "Priya Sharma",
    "status": "paused"
};

fetch(url, {
    method: "PATCH",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "id": 42,
    "external_id": "client-8821",
    "name": "Priya Nair",
    "status": "paused",
    "language": "en"
}
 

Example response (404):


{
    "message": "Client not found."
}
 

Request      

PATCH api/partner/v1/clients/{externalId}

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

externalId   string     

Your own record id for this client. Example: client-8821

Body Parameters

name   string  optional    

Client's full name. Example: Priya Sharma

status   string  optional    

Client's status: active, paused, or archived. Example: paused