Skip to content
WhatsMarketingDeveloper Hub

Contacts

The people your organization talks to: details, lifecycle stage, tags, channel identities, consent and notes. A contact can have several identities (their WhatsApp, their Instagram, their email) and all of them point to the same record.

List contacts

GET/contacts

The organization's contacts, paginated and with filters: tab (tab), stage, owner (ownerId, or none for those without one), source, channel, tag, free-text search (q) or recent activity (days). Besides data and meta it includes tabs (how many are in each tab) and summary (the dashboard header figures).

Scopes: contacts:read

Parameters

NameWhereTypeValues
pagequerynumberdefault: 1 · 1 – …
pageSizequerynumberdefault: 20 · 1 – 100
tabquerystringall · leads · in_progress · customers · inactive · no_consent
lifecycleStageIdqueryuuid
ownerIdquerystring^(none|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$
sourcequerystringOTHER · MANUAL · IMPORT · WHATSAPP_INBOUND · CAMPAIGN · WEBSITE_FORM · REFERRAL
channelTypequerystringWHATSAPP · INSTAGRAM · MESSENGER · FACEBOOK · TELEGRAM · TIKTOK · WEBCHAT · EMAIL · SMS · WECHAT · VOICE
tagquerystring0–60 characters
qquerystring0–120 characters
searchquerystring0–120 characters
daysquerynumber7 · 30 · 90
idsqueryuuid[]≤ 500
curl
curl "https://micuenta.whatsmarketing.es/api/v1/contacts?page=1&pageSize=20" \
  -H "Authorization: Bearer $WM_API_KEY"
Node.js
const res = await fetch('https://micuenta.whatsmarketing.es/api/v1/contacts?page=1&pageSize=20', {
  headers: {
    Authorization: `Bearer ${process.env.WM_API_KEY}`,
  },
});
const data = await res.json();
Python
import os, requests

r = requests.get(
    "https://micuenta.whatsmarketing.es/api/v1/contacts?page=1&pageSize=20",
    headers={"Authorization": f"Bearer {os.environ['WM_API_KEY']}"},
    timeout=30,
)
r.raise_for_status()
data = r.json()
PHP
<?php
$ch = curl_init('https://micuenta.whatsmarketing.es/api/v1/contacts?page=1&pageSize=20');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    'Authorization: Bearer ' . getenv('WM_API_KEY'),
  ],
]);
$data = json_decode(curl_exec($ch), true);
Response 200
{
  "data": [
    {
      "id": "0b1c2d3e-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
      "fullName": "Laura Pérez",
      "primaryPhone": "+34612345678",
      "primaryEmail": "laura@ejemplo.com",
      "company": "Clínica Sol",
      "country": "ES",
      "source": "WEBSITE_FORM",
      "lifecycleStageId": "9c2a1f00-2b3c-4d5e-8f90-1a2b3c4d5e6f",
      "lifecycleStage": {
        "id": "9c2a1f00-2b3c-4d5e-8f90-1a2b3c4d5e6f",
        "name": "Lead nuevo",
        "order": 1
      },
      "ownerId": null,
      "owner": null,
      "optedOut": false,
      "consent": {
        "given": true,
        "at": "2026-10-14T10:20:00.000Z",
        "how": "WEBSITE_FORM"
      },
      "tags": [
        "web"
      ],
      "identities": [
        {
          "id": "6d7e8f90-1a2b-4c3d-9e4f-5a6b7c8d9e0f",
          "channelType": "WHATSAPP",
          "externalId": "34612345678"
        }
      ],
      "lastConversation": null,
      "createdAt": "2026-10-14T10:20:05.000Z",
      "updatedAt": "2026-10-14T10:20:05.000Z"
    }
  ],
  "meta": {
    "page": 1,
    "pageSize": 20,
    "total": 1,
    "totalPages": 1
  },
  "tabs": {
    "all": 1,
    "leads": 1,
    "in_progress": 0,
    "customers": 0,
    "inactive": 0,
    "no_consent": 0
  },
  "summary": {
    "days": 30,
    "total": 1,
    "newInPeriod": 1,
    "withConsent": 1,
    "withoutConsent": 0,
    "consentPct": 100,
    "leadsNew": 1,
    "leadsInProgress": 0,
    "customers": 0,
    "customersNewInPeriod": 0,
    "tags": [
      "web"
    ]
  }
}

Create a contact

POST/contacts

Creates the record. The phone goes in international format with prefix (+34…). If a contact with that phone already exists, it responds 409 CONTACT_PHONE_EXISTS with the existing contactId. consent records when and how the person consented to receive messages; note leaves a first internal note.

Scopes: contacts:write

Request body CreateContact

NameTypeValues
fullNamestring0–160 characters
primaryPhonestring0–32 characters
primaryEmailemail
companystring0–160 characters
countrystring0–2 characters
sourcestringOTHER · MANUAL · IMPORT · WHATSAPP_INBOUND · CAMPAIGN · WEBSITE_FORM · REFERRAL
lifecycleStageIduuid
ownerIduuid
optedOutboolean
consentConsent
tagsstring[]≤ 50
notestring0–4000 characters

Common errors

  • 409 CONTACT_PHONE_EXISTS A contact with that phone already exists; the response includes contactId and fullName.
curl
curl -X POST "https://micuenta.whatsmarketing.es/api/v1/contacts" \
  -H "Authorization: Bearer $WM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "fullName": "Laura Pérez",
  "primaryPhone": "+34612345678",
  "primaryEmail": "laura@ejemplo.com",
  "company": "Clínica Sol",
  "country": "ES",
  "source": "WEBSITE_FORM",
  "tags": [
    "web"
  ],
  "consent": {
    "given": true,
    "at": "2026-10-14T10:20:00.000Z",
    "how": "WEBSITE_FORM"
  }
}'
Node.js
const res = await fetch('https://micuenta.whatsmarketing.es/api/v1/contacts', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.WM_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "fullName": "Laura Pérez",
    "primaryPhone": "+34612345678",
    "primaryEmail": "laura@ejemplo.com",
    "company": "Clínica Sol",
    "country": "ES",
    "source": "WEBSITE_FORM",
    "tags": [
      "web"
    ],
    "consent": {
      "given": true,
      "at": "2026-10-14T10:20:00.000Z",
      "how": "WEBSITE_FORM"
    }
  }),
});
const data = await res.json();
Python
import os, requests

r = requests.post(
    "https://micuenta.whatsmarketing.es/api/v1/contacts",
    headers={"Authorization": f"Bearer {os.environ['WM_API_KEY']}"},
    json={
        "fullName": "Laura Pérez",
        "primaryPhone": "+34612345678",
        "primaryEmail": "laura@ejemplo.com",
        "company": "Clínica Sol",
        "country": "ES",
        "source": "WEBSITE_FORM",
        "tags": [
            "web"
        ],
        "consent": {
            "given": True,
            "at": "2026-10-14T10:20:00.000Z",
            "how": "WEBSITE_FORM"
        }
    },
    timeout=30,
)
r.raise_for_status()
data = r.json()
PHP
<?php
$ch = curl_init('https://micuenta.whatsmarketing.es/api/v1/contacts');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_HTTPHEADER => [
    'Authorization: Bearer ' . getenv('WM_API_KEY'),
    'Content-Type: application/json',
  ],
  CURLOPT_POSTFIELDS => json_encode([
    'fullName' => 'Laura Pérez',
    'primaryPhone' => '+34612345678',
    'primaryEmail' => 'laura@ejemplo.com',
    'company' => 'Clínica Sol',
    'country' => 'ES',
    'source' => 'WEBSITE_FORM',
    'tags' => [
      'web'
    ],
    'consent' => [
      'given' => true,
      'at' => '2026-10-14T10:20:00.000Z',
      'how' => 'WEBSITE_FORM'
    ]
  ]),
]);
$data = json_decode(curl_exec($ch), true);
Response 201
{
  "id": "0b1c2d3e-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
  "organizationId": "f0e1d2c3-b4a5-4968-8776-655443322110",
  "fullName": "Laura Pérez",
  "primaryPhone": "+34612345678",
  "primaryEmail": "laura@ejemplo.com",
  "company": "Clínica Sol",
  "country": "ES",
  "source": "WEBSITE_FORM",
  "lifecycleStageId": null,
  "lifecycleStage": null,
  "ownerId": null,
  "owner": null,
  "optedOut": false,
  "consent": {
    "given": true,
    "at": "2026-10-14T10:20:00.000Z",
    "how": "WEBSITE_FORM"
  },
  "tags": [
    "web"
  ],
  "identities": [
    {
      "id": "6d7e8f90-1a2b-4c3d-9e4f-5a6b7c8d9e0f",
      "channelType": "WHATSAPP",
      "externalId": "34612345678"
    }
  ],
  "createdAt": "2026-10-14T10:20:05.000Z",
  "updatedAt": "2026-10-14T10:20:05.000Z"
}

Bulk update contacts

POST/contacts/bulk

Up to 500 contacts per call: change the stage, add tags (up to 20) or reassign the owner (ownerId: null removes it). At least one of the three. skipped are the ids that don't belong to your organization.

Scopes: contacts:write

Request body BulkContacts

NameTypeValues
ids requireduuid[]≤ 500
lifecycleStageIduuid
addTagsstring[]≤ 20
ownerIduuid
curl
curl -X POST "https://micuenta.whatsmarketing.es/api/v1/contacts/bulk" \
  -H "Authorization: Bearer $WM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "ids": [
    "0b1c2d3e-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
    "4e5f6a7b-8c9d-4e0f-9a1b-2c3d4e5f6a7b"
  ],
  "addTags": [
    "evento-madrid"
  ],
  "lifecycleStageId": "9c2a1f00-2b3c-4d5e-8f90-1a2b3c4d5e6f"
}'
Node.js
const res = await fetch('https://micuenta.whatsmarketing.es/api/v1/contacts/bulk', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.WM_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "ids": [
      "0b1c2d3e-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
      "4e5f6a7b-8c9d-4e0f-9a1b-2c3d4e5f6a7b"
    ],
    "addTags": [
      "evento-madrid"
    ],
    "lifecycleStageId": "9c2a1f00-2b3c-4d5e-8f90-1a2b3c4d5e6f"
  }),
});
const data = await res.json();
Python
import os, requests

r = requests.post(
    "https://micuenta.whatsmarketing.es/api/v1/contacts/bulk",
    headers={"Authorization": f"Bearer {os.environ['WM_API_KEY']}"},
    json={
        "ids": [
            "0b1c2d3e-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
            "4e5f6a7b-8c9d-4e0f-9a1b-2c3d4e5f6a7b"
        ],
        "addTags": [
            "evento-madrid"
        ],
        "lifecycleStageId": "9c2a1f00-2b3c-4d5e-8f90-1a2b3c4d5e6f"
    },
    timeout=30,
)
r.raise_for_status()
data = r.json()
PHP
<?php
$ch = curl_init('https://micuenta.whatsmarketing.es/api/v1/contacts/bulk');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_HTTPHEADER => [
    'Authorization: Bearer ' . getenv('WM_API_KEY'),
    'Content-Type: application/json',
  ],
  CURLOPT_POSTFIELDS => json_encode([
    'ids' => [
      '0b1c2d3e-5f6a-4b7c-8d9e-0f1a2b3c4d5e',
      '4e5f6a7b-8c9d-4e0f-9a1b-2c3d4e5f6a7b'
    ],
    'addTags' => [
      'evento-madrid'
    ],
    'lifecycleStageId' => '9c2a1f00-2b3c-4d5e-8f90-1a2b3c4d5e6f'
  ]),
]);
$data = json_decode(curl_exec($ch), true);
Response 201
{
  "updated": 2,
  "skipped": 0
}

Get a contact

GET/contacts/{id}

The full record: channel identities, consent, tags, owner, stage and open deals.

Scopes: contacts:read

Parameters

NameWhereTypeValues
id requiredpathstring
curl
curl "https://micuenta.whatsmarketing.es/api/v1/contacts/{id}" \
  -H "Authorization: Bearer $WM_API_KEY"
Node.js
const res = await fetch('https://micuenta.whatsmarketing.es/api/v1/contacts/{id}', {
  headers: {
    Authorization: `Bearer ${process.env.WM_API_KEY}`,
  },
});
const data = await res.json();
Python
import os, requests

r = requests.get(
    "https://micuenta.whatsmarketing.es/api/v1/contacts/{id}",
    headers={"Authorization": f"Bearer {os.environ['WM_API_KEY']}"},
    timeout=30,
)
r.raise_for_status()
data = r.json()
PHP
<?php
$ch = curl_init('https://micuenta.whatsmarketing.es/api/v1/contacts/{id}');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    'Authorization: Bearer ' . getenv('WM_API_KEY'),
  ],
]);
$data = json_decode(curl_exec($ch), true);
Response 200
{
  "id": "0b1c2d3e-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
  "organizationId": "f0e1d2c3-b4a5-4968-8776-655443322110",
  "fullName": "Laura Pérez",
  "primaryPhone": "+34612345678",
  "primaryEmail": "laura@ejemplo.com",
  "company": "Clínica Sol",
  "country": "ES",
  "source": "WEBSITE_FORM",
  "lifecycleStageId": null,
  "lifecycleStage": null,
  "ownerId": null,
  "owner": null,
  "optedOut": false,
  "consent": {
    "given": true,
    "at": "2026-10-14T10:20:00.000Z",
    "how": "WEBSITE_FORM"
  },
  "tags": [
    "web"
  ],
  "identities": [
    {
      "id": "6d7e8f90-1a2b-4c3d-9e4f-5a6b7c8d9e0f",
      "channelType": "WHATSAPP",
      "externalId": "34612345678"
    }
  ],
  "createdAt": "2026-10-14T10:20:05.000Z",
  "updatedAt": "2026-10-14T10:20:05.000Z"
}

Update a contact

PATCH/contacts/{id}

All fields are optional; only what you send changes. Changing the phone to one that another contact already has responds 409 CONTACT_PHONE_EXISTS. Responds with the updated record.

Scopes: contacts:write

Parameters

NameWhereTypeValues
id requiredpathstring

Request body UpdateContact

NameTypeValues
fullNamestring0–160 characters
primaryPhonestring0–32 characters
primaryEmailemail
companystring0–160 characters
countrystring0–2 characters
sourcestringOTHER · MANUAL · IMPORT · WHATSAPP_INBOUND · CAMPAIGN · WEBSITE_FORM · REFERRAL
lifecycleStageIduuid
ownerIduuid
optedOutboolean
consentConsent
tagsstring[]≤ 50
curl
curl -X PATCH "https://micuenta.whatsmarketing.es/api/v1/contacts/{id}" \
  -H "Authorization: Bearer $WM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "company": "Clínica Sol Fuengirola",
  "tags": [
    "web",
    "cliente"
  ],
  "lifecycleStageId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
}'
Node.js
const res = await fetch('https://micuenta.whatsmarketing.es/api/v1/contacts/{id}', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.WM_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "company": "Clínica Sol Fuengirola",
    "tags": [
      "web",
      "cliente"
    ],
    "lifecycleStageId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
  }),
});
const data = await res.json();
Python
import os, requests

r = requests.patch(
    "https://micuenta.whatsmarketing.es/api/v1/contacts/{id}",
    headers={"Authorization": f"Bearer {os.environ['WM_API_KEY']}"},
    json={
        "company": "Clínica Sol Fuengirola",
        "tags": [
            "web",
            "cliente"
        ],
        "lifecycleStageId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
    },
    timeout=30,
)
r.raise_for_status()
data = r.json()
PHP
<?php
$ch = curl_init('https://micuenta.whatsmarketing.es/api/v1/contacts/{id}');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'PATCH',
  CURLOPT_HTTPHEADER => [
    'Authorization: Bearer ' . getenv('WM_API_KEY'),
    'Content-Type: application/json',
  ],
  CURLOPT_POSTFIELDS => json_encode([
    'company' => 'Clínica Sol Fuengirola',
    'tags' => [
      'web',
      'cliente'
    ],
    'lifecycleStageId' => 'a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d'
  ]),
]);
$data = json_decode(curl_exec($ch), true);
Response 200
{
  "id": "0b1c2d3e-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
  "organizationId": "f0e1d2c3-b4a5-4968-8776-655443322110",
  "fullName": "Laura Pérez",
  "primaryPhone": "+34612345678",
  "primaryEmail": "laura@ejemplo.com",
  "company": "Clínica Sol",
  "country": "ES",
  "source": "WEBSITE_FORM",
  "lifecycleStageId": null,
  "lifecycleStage": null,
  "ownerId": null,
  "owner": null,
  "optedOut": false,
  "consent": {
    "given": true,
    "at": "2026-10-14T10:20:00.000Z",
    "how": "WEBSITE_FORM"
  },
  "tags": [
    "web"
  ],
  "identities": [
    {
      "id": "6d7e8f90-1a2b-4c3d-9e4f-5a6b7c8d9e0f",
      "channelType": "WHATSAPP",
      "externalId": "34612345678"
    }
  ],
  "createdAt": "2026-10-14T10:20:05.000Z",
  "updatedAt": "2026-10-14T10:20:05.000Z"
}

Delete a contact

DELETE/contacts/{id}

Only if the contact has no conversations, campaigns or deals; if it does, it responds 409 CONTACT_HAS_HISTORY and it's better to withdraw their consent (optedOut: true) instead of deleting. Notes and identities are deleted along with it.

Scopes: contacts:write

Parameters

NameWhereTypeValues
id requiredpathstring

Common errors

  • 409 CONTACT_HAS_HISTORY The contact has history: it isn't deleted so that reports keep adding up.
curl
curl -X DELETE "https://micuenta.whatsmarketing.es/api/v1/contacts/{id}" \
  -H "Authorization: Bearer $WM_API_KEY"
Node.js
const res = await fetch('https://micuenta.whatsmarketing.es/api/v1/contacts/{id}', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${process.env.WM_API_KEY}`,
  },
});
const data = await res.json();
Python
import os, requests

r = requests.delete(
    "https://micuenta.whatsmarketing.es/api/v1/contacts/{id}",
    headers={"Authorization": f"Bearer {os.environ['WM_API_KEY']}"},
    timeout=30,
)
r.raise_for_status()
data = r.json()
PHP
<?php
$ch = curl_init('https://micuenta.whatsmarketing.es/api/v1/contacts/{id}');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'DELETE',
  CURLOPT_HTTPHEADER => [
    'Authorization: Bearer ' . getenv('WM_API_KEY'),
  ],
]);
$data = json_decode(curl_exec($ch), true);
Response 200
{
  "deleted": true
}

Contact timeline

GET/contacts/{id}/timeline

Conversations, campaigns received, notes, stage changes, consent and creation, in reverse chronological order. type filters by conversations, campaigns or notes; each entry carries its type.

Scopes: contacts:read

Parameters

NameWhereTypeValues
id requiredpathstring
pagequerynumberdefault: 1 · 1 – …
pageSizequerynumberdefault: 20 · 1 – 100
typequerystringall · conversations · campaigns · notes
curl
curl "https://micuenta.whatsmarketing.es/api/v1/contacts/{id}/timeline?page=1&pageSize=20" \
  -H "Authorization: Bearer $WM_API_KEY"
Node.js
const res = await fetch('https://micuenta.whatsmarketing.es/api/v1/contacts/{id}/timeline?page=1&pageSize=20', {
  headers: {
    Authorization: `Bearer ${process.env.WM_API_KEY}`,
  },
});
const data = await res.json();
Python
import os, requests

r = requests.get(
    "https://micuenta.whatsmarketing.es/api/v1/contacts/{id}/timeline?page=1&pageSize=20",
    headers={"Authorization": f"Bearer {os.environ['WM_API_KEY']}"},
    timeout=30,
)
r.raise_for_status()
data = r.json()
PHP
<?php
$ch = curl_init('https://micuenta.whatsmarketing.es/api/v1/contacts/{id}/timeline?page=1&pageSize=20');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    'Authorization: Bearer ' . getenv('WM_API_KEY'),
  ],
]);
$data = json_decode(curl_exec($ch), true);
Response 200
{
  "data": [
    {
      "id": "7c8d9e0f-1a2b-4c3d-8e4f-5a6b7c8d9e0f",
      "type": "campaign",
      "at": "2026-10-10T08:00:00.000Z",
      "campaign": {
        "id": "3a4b5c6d-7e8f-4a9b-8c0d-1e2f3a4b5c6d",
        "name": "Octubre: promo"
      },
      "status": "DELIVERED",
      "sentAt": "2026-10-10T08:00:02.000Z",
      "deliveredAt": "2026-10-10T08:00:05.000Z",
      "readAt": null,
      "failedAt": null,
      "errorMessage": null
    },
    {
      "id": "8d9e0f1a-2b3c-4d4e-9f5a-6b7c8d9e0f1a",
      "type": "note",
      "at": "2026-10-09T17:12:00.000Z",
      "author": "Ana Gómez",
      "body": "Pidió presupuesto por teléfono"
    },
    {
      "id": "9e0f1a2b-3c4d-4e5f-8a6b-7c8d9e0f1a2b",
      "type": "stage",
      "at": "2026-10-09T17:00:00.000Z",
      "by": "Ana Gómez",
      "from": "Lead nuevo",
      "to": "En proceso",
      "bulk": false
    },
    {
      "id": "0b1c2d3e-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
      "type": "created",
      "at": "2026-10-01T09:00:00.000Z",
      "source": "WEBSITE_FORM"
    }
  ],
  "meta": {
    "page": 1,
    "pageSize": 20,
    "total": 4,
    "totalPages": 1
  }
}

Add a channel identity

POST/contacts/{id}/identities

Links another channel to the same record: channelType is the channel type (WHATSAPP, INSTAGRAM, MESSENGER, EMAIL…) and externalId the contact's identifier on that channel (phone without + for WhatsApp, username for Instagram, address for email). If that identity already belongs to another contact, it responds 409.

Scopes: contacts:write

Parameters

NameWhereTypeValues
id requiredpathstring

Request body AddIdentity

NameTypeValues
channelType requiredstringWHATSAPP · INSTAGRAM · MESSENGER · FACEBOOK · TELEGRAM · TIKTOK · WEBCHAT · EMAIL · SMS · WECHAT · VOICE
externalId requiredstring
curl
curl -X POST "https://micuenta.whatsmarketing.es/api/v1/contacts/{id}/identities" \
  -H "Authorization: Bearer $WM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "channelType": "INSTAGRAM",
  "externalId": "laura.perez"
}'
Node.js
const res = await fetch('https://micuenta.whatsmarketing.es/api/v1/contacts/{id}/identities', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.WM_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "channelType": "INSTAGRAM",
    "externalId": "laura.perez"
  }),
});
const data = await res.json();
Python
import os, requests

r = requests.post(
    "https://micuenta.whatsmarketing.es/api/v1/contacts/{id}/identities",
    headers={"Authorization": f"Bearer {os.environ['WM_API_KEY']}"},
    json={
        "channelType": "INSTAGRAM",
        "externalId": "laura.perez"
    },
    timeout=30,
)
r.raise_for_status()
data = r.json()
PHP
<?php
$ch = curl_init('https://micuenta.whatsmarketing.es/api/v1/contacts/{id}/identities');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_HTTPHEADER => [
    'Authorization: Bearer ' . getenv('WM_API_KEY'),
    'Content-Type: application/json',
  ],
  CURLOPT_POSTFIELDS => json_encode([
    'channelType' => 'INSTAGRAM',
    'externalId' => 'laura.perez'
  ]),
]);
$data = json_decode(curl_exec($ch), true);
Response 201
{
  "id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
  "contactId": "0b1c2d3e-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
  "channelId": "5f6a7b8c-9d0e-4f1a-8b2c-3d4e5f6a7b8c",
  "channel": {
    "id": "5f6a7b8c-9d0e-4f1a-8b2c-3d4e5f6a7b8c",
    "type": "INSTAGRAM"
  },
  "externalId": "laura.perez"
}

List contact notes

GET/contacts/{id}/notes

Internal team notes, from newest to oldest, with author and date.

Scopes: contacts:read

Parameters

NameWhereTypeValues
id requiredpathstring
pagequerynumberdefault: 1 · 1 – …
pageSizequerynumberdefault: 20 · 1 – 100
curl
curl "https://micuenta.whatsmarketing.es/api/v1/contacts/{id}/notes?page=1&pageSize=20" \
  -H "Authorization: Bearer $WM_API_KEY"
Node.js
const res = await fetch('https://micuenta.whatsmarketing.es/api/v1/contacts/{id}/notes?page=1&pageSize=20', {
  headers: {
    Authorization: `Bearer ${process.env.WM_API_KEY}`,
  },
});
const data = await res.json();
Python
import os, requests

r = requests.get(
    "https://micuenta.whatsmarketing.es/api/v1/contacts/{id}/notes?page=1&pageSize=20",
    headers={"Authorization": f"Bearer {os.environ['WM_API_KEY']}"},
    timeout=30,
)
r.raise_for_status()
data = r.json()
PHP
<?php
$ch = curl_init('https://micuenta.whatsmarketing.es/api/v1/contacts/{id}/notes?page=1&pageSize=20');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    'Authorization: Bearer ' . getenv('WM_API_KEY'),
  ],
]);
$data = json_decode(curl_exec($ch), true);
Response 200
{
  "data": [
    {
      "id": "8d9e0f1a-2b3c-4d4e-9f5a-6b7c8d9e0f1a",
      "contactId": "0b1c2d3e-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
      "authorId": "2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
      "author": {
        "id": "2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
        "fullName": "Ana Gómez"
      },
      "body": "Pidió presupuesto por teléfono",
      "createdAt": "2026-10-09T17:12:00.000Z"
    }
  ],
  "meta": {
    "page": 1,
    "pageSize": 20,
    "total": 1,
    "totalPages": 1
  }
}

Add a note

POST/contacts/{id}/notes

The note is attributed to the user who created the API key.

Scopes: contacts:write

Parameters

NameWhereTypeValues
id requiredpathstring

Request body CreateContactNote

NameTypeValues
body requiredstring1–… characters
curl
curl -X POST "https://micuenta.whatsmarketing.es/api/v1/contacts/{id}/notes" \
  -H "Authorization: Bearer $WM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "body": "Llamada hecha: le interesa el plan Pyme."
}'
Node.js
const res = await fetch('https://micuenta.whatsmarketing.es/api/v1/contacts/{id}/notes', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.WM_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "body": "Llamada hecha: le interesa el plan Pyme."
  }),
});
const data = await res.json();
Python
import os, requests

r = requests.post(
    "https://micuenta.whatsmarketing.es/api/v1/contacts/{id}/notes",
    headers={"Authorization": f"Bearer {os.environ['WM_API_KEY']}"},
    json={
        "body": "Llamada hecha: le interesa el plan Pyme."
    },
    timeout=30,
)
r.raise_for_status()
data = r.json()
PHP
<?php
$ch = curl_init('https://micuenta.whatsmarketing.es/api/v1/contacts/{id}/notes');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_HTTPHEADER => [
    'Authorization: Bearer ' . getenv('WM_API_KEY'),
    'Content-Type: application/json',
  ],
  CURLOPT_POSTFIELDS => json_encode([
    'body' => 'Llamada hecha: le interesa el plan Pyme.'
  ]),
]);
$data = json_decode(curl_exec($ch), true);
Response 201
{
  "id": "4c5d6e7f-8a9b-4c0d-9e1f-2a3b4c5d6e7f",
  "contactId": "0b1c2d3e-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
  "authorId": "2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
  "author": {
    "id": "2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
    "fullName": "Ana Gómez"
  },
  "body": "Llamada hecha: le interesa el plan Pyme.",
  "createdAt": "2026-10-14T11:00:00.000Z"
}

Schemas

Consent

NameTypeValues
given requiredboolean
atstring
howstringOTHER · WEBSITE_FORM · PHONE · WHATSAPP_REPLY · CONTRACT