ataca/connect docs
Dashboard

API Reference

Complete REST API reference with request/response examples for all endpoints.

Response envelope

All API responses use a consistent envelope:

{
  "status": "ok",
  "time": "2026-04-06T10:00:00.000000000Z",
  "request_id": "01jqk...",
  "data": {}
}
Field Description
status "ok" on success, "error" on failure
time Server timestamp (RFC3339 nanoseconds)
request_id Unique request identifier (base32-encoded UUIDv7)
data Response payload (object or array). Reads return it; creates return the new id at the top level instead

On error, data is omitted and an error field contains the message:

{
  "status": "error",
  "time": "2026-04-06T10:00:00.000000000Z",
  "request_id": "01jqk...",
  "error": "contact not found"
}

GET /v1/who

Returns information about the authenticated API key and tenant.

curl -H "Authorization: Bearer $API_KEY" https://connect.ataca.io/v1/who
{
  "status": "ok",
  "data": {
    "tenant": "acme",
    "key_name": "production-key",
    "created_by": "[email protected]"
  }
}

POST /v1/contacts

Create a new contact.

Field Type Required Description
number string yes Phone number in E.164 format, for example +14155552671
email string no Email address
reference string no Your custom identifier for this contact

number is required. email and reference are optional.

curl -X POST https://connect.ataca.io/v1/contacts \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"number": "+1234567890", "email": "[email protected]", "reference": "cust-001"}'
{
  "status": "ok",
  "id": "01jqk...",
  "time": "2026-04-06T10:00:00.000000000Z",
  "request_id": "acme-b7k9m2n4p6"
}

The response carries the new contact's id only. Fetch the contact with GET /v1/contacts/{id}.

Uniqueness: Contacts are unique per tenant by number and by reference. Attempting to create a duplicate returns HTTP 409 Conflict.

GET /v1/contacts

List contacts with pagination.

Query param Default Description
page 1 Page number
page_size 20 Items per page (max 100)
curl -H "Authorization: Bearer $API_KEY" "https://connect.ataca.io/v1/contacts?page=1&page_size=10"
{
  "status": "ok",
  "data": {
    "contacts": [
      {
        "id": "01jqk...",
        "number": "+1234567890",
        "email": "[email protected]",
        "reference": "cust-001",
        "created_at": "2026-04-06T10:00:00.000000000Z"
      }
    ],
    "total": 42,
    "page": 1,
    "page_size": 10
  }
}

GET /v1/contacts/{id}

Get a single contact by ID.

curl -H "Authorization: Bearer $API_KEY" https://connect.ataca.io/v1/contacts/01jqk...
{
  "status": "ok",
  "data": {
    "id": "01jqk...",
    "number": "+1234567890",
    "email": "[email protected]",
    "reference": "cust-001",
    "created_at": "2026-04-06T10:00:00.000000000Z"
  }
}

Returns HTTP 404 if the contact does not exist or belongs to a different tenant.

GET /v1/templates

List all templates with aggregated placeholder information across channels.

curl -H "Authorization: Bearer $API_KEY" https://connect.ataca.io/v1/templates
{
  "status": "ok",
  "data": {
    "templates": [
      {
        "id": "01jqk...",
        "name": "welcome",
        "description": "Welcome message for new users",
        "channels": ["WHATSAPP", "EMAIL", "SMS"],
        "placeholders": [
          {"name": "first_name", "required": true},
          {"name": "discount", "required": false, "default": "10%"}
        ],
        "created_at": "2026-04-06T10:00:00.000000000Z",
        "updated_at": "2026-04-06T10:00:00.000000000Z"
      }
    ]
  }
}

Placeholders are aggregated from all channel bodies. A placeholder is required if it appears without a default in any channel body.

POST /v1/send

Send a message to a contact using a template.

Field Type Required Description
contact_id string yes Contact ID (base32-encoded)
template string yes Template name
data object no Placeholder values
file_id string no An uploaded file's id. Its link becomes the file_url placeholder
curl -X POST https://connect.ataca.io/v1/send \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contact_id": "01jqk...",
    "template": "welcome",
    "data": {"first_name": "Alice", "discount": "20%"}
  }'
{
  "status": "ok",
  "id": "01jqk...",
  "time": "2026-04-06T10:01:00.000000000Z",
  "request_id": "acme-j8k2m4n6p8"
}

The response carries the new message's id only. The message is enqueued for async delivery. The delivery orchestrator processes it through your configured cascade policy. Check delivery status via the dashboard or webhook callbacks.

POST /v1/files

Upload a file to attach to messages. Send one multipart form part named file. The default size limit is 10 MB.

curl -X POST https://connect.ataca.io/v1/files \
  -H "Authorization: Bearer $API_KEY" \
  -F "[email protected];type=application/pdf"
{
  "status": "ok",
  "file": {
    "id": "k7m2p9q4r1s8t3v6",
    "url": "https://connect.ataca.io/f/k7m2p9q4r1s8t3v6",
    "name": "invoice.pdf",
    "content_type": "application/pdf",
    "size": 48213,
    "expires_at": "2026-04-13T10:01:00Z"
  }
}

Pass the id as file_id on POST /v1/send and reference {{file_url}} in the template body. The link is public: anyone who has it can fetch the file. The random id is what keeps it private.

A file expires seven days after upload by default (files.ttl_days). After that, or after a delete, its link answers 410 Gone and POST /v1/send rejects its file_id with 400 file expired or deleted. An hourly sweep removes the bytes of expired files.

DELETE /v1/files/{id}

Revoke a file before it expires. Its bytes are removed at once and its link answers 410 Gone from then on. Deleting a file that is already gone succeeds; an id that is not yours answers 404.

curl -X DELETE https://connect.ataca.io/v1/files/k7m2p9q4r1s8t3v6 \
  -H "Authorization: Bearer $API_KEY"
{
  "status": "ok",
  "id": "k7m2p9q4r1s8t3v6",
  "time": "2026-04-06T10:05:00.000000000Z",
  "request_id": "acme-j8k2m4n6p9"
}

GET /f/{id}

Fetch an uploaded file. No authentication; rate limited per IP. Images, PDF, plain text, audio, and video are served inline. Everything else downloads as an opaque attachment, so nothing uploaded can run in a browser on this origin. An expired or deleted file answers 410 Gone; an unknown id answers 404.

Pagination

List endpoints support page and page_size query parameters. Responses include a total count for computing page ranges.

Parameter Default Max Description
page 1 — 1-indexed page number
page_size 20 100 Number of items per page