Skip to content

Create or update a contact ​

POST/v1/contacts

The contact of the number to (with the country code): created when the account has none (201), else changed (200). name replaces the name (null clears it); fields — values of custom fields by key (GET /v1/fields), only the keys sent change, null removes one. Campaigns fill the variables {{key}} from these values. Refusals: invalid_number, validation_failed (fields.{key} in — no such field, field_value — not a value of its type). Keys with the contacts permission.

API key permission: contacts · Limit: 50 requests a second per key

Request body ​

FieldTypeRequiredDescription
tostringyesThe number with the country code (E.164, «+5511912345678»), as for a message. Up to 32 characters.
namestring, nullableUp to 120 characters; null or blank clears it; left out keeps it. Up to 120 characters.
fieldsobjectValues of custom fields by key (GET /fields): only the keys sent change; null removes a value. Keys map to string, nullable values.

Request ​

bash
curl -X POST "https://api.ace-send.com/v1/contacts" \
  -H "Authorization: Bearer ak_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+5521998120937",
    "name": "Ana Souza",
    "fields": {
      "promo_code": "VIP25",
      "amount": "150",
      "vip_since": "2026-09-14"
    }
  }'
js
const response = await fetch('https://api.ace-send.com/v1/contacts', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.ACE_SEND_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "to": "+5521998120937",
    "name": "Ana Souza",
    "fields": {
      "promo_code": "VIP25",
      "amount": "150",
      "vip_since": "2026-09-14"
    }
  }),
})
const result = await response.json()

if (!response.ok) {
  // application/problem+json: result.code is stable, result.title is for people
  throw new Error(`${result.code}: ${result.title}`)
}
console.log(result)
python
import os

import requests

headers = {
    "Authorization": f"Bearer {os.environ['ACE_SEND_API_KEY']}",
}
response = requests.post(
    "https://api.ace-send.com/v1/contacts",
    headers=headers,
    json={
        "to": "+5521998120937",
        "name": "Ana Souza",
        "fields": {
            "promo_code": "VIP25",
            "amount": "150",
            "vip_since": "2026-09-14",
        },
    },
    timeout=10,
)
result = response.json()

if not response.ok:
    # application/problem+json: result["code"] is stable, result["title"] is for people
    raise RuntimeError(f"{result['code']}: {result['title']}")
print(result)
php
<?php

// composer require guzzlehttp/guzzle
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.ace-send.com/v1/']);

$response = $client->request('POST', 'contacts', [
    'headers' => [
        'Authorization' => 'Bearer '.getenv('ACE_SEND_API_KEY'),
    ],
    'json' => [
        'to' => '+5521998120937',
        'name' => 'Ana Souza',
        'fields' => [
            'promo_code' => 'VIP25',
            'amount' => '150',
            'vip_since' => '2026-09-14',
        ],
    ],
    'http_errors' => false,
]);
$result = json_decode((string) $response->getBody(), true);

if ($response->getStatusCode() >= 400) {
    // application/problem+json: $result['code'] is stable, $result['title'] is for people
    throw new RuntimeException($result['code'].': '.$result['title']);
}
print_r($result);

Response ​

200 OK ​

FieldTypeDescription
idstringThe contact, cnt_….
tostringE.164, as messages are sent to it.
namestring, nullableThe name of the contact.
fieldsobjectValues of custom fields by key, as kept: text, a number or an amount as «1234.5», a date as «2026-10-30». Keys map to string values.
created_atstringWhen the contact was created.
updated_atstringWhen the contact last changed.
json
{
  "id": "cnt_CgdWeHQNoWb5T3WhuKxnx",
  "to": "+5521998120937",
  "name": "Ana Souza",
  "fields": {
    "promo_code": "VIP25",
    "amount": "150",
    "vip_since": "2026-09-14"
  },
  "created_at": "2026-10-30T08:15:00+00:00",
  "updated_at": "2026-11-02T12:00:00+00:00"
}

201 Created ​

FieldTypeDescription
idstringThe contact, cnt_….
tostringE.164, as messages are sent to it.
namestring, nullableThe name of the contact.
fieldsobjectValues of custom fields by key, as kept: text, a number or an amount as «1234.5», a date as «2026-10-30». Keys map to string values.
created_atstringWhen the contact was created.
updated_atstringWhen the contact last changed.
json
{
  "id": "cnt_CgdWeHQNoWb5T3WhuKxnx",
  "to": "+5521998120937",
  "name": "Ana Souza",
  "fields": {
    "promo_code": "VIP25",
    "amount": "150",
    "vip_since": "2026-09-14"
  },
  "created_at": "2026-11-02T12:00:00+00:00",
  "updated_at": "2026-11-02T12:00:00+00:00"
}

Errors ​

Errors are application/problem+json with a stable code (all codes). Besides the errors of every request (an invalid key, a missing permission, too many requests), this endpoint answers:

StatusCodeMeaning
422invalid_numberThe number is not a valid phone number. Send it in E.164: +, the country code and the number, without spaces or dashes.
422validation_failedSome fields are wrong: errors lists each field with its code and a message.
json
{
  "type": "about:blank",
  "status": 422,
  "code": "invalid_number",
  "title": "The recipient's number is not valid"
}

ACE SEND API v1