Aitarax

Documentation

Get from signup to first email in under 15 minutes.

Quick start

1. Create an account at app.aitarax.com

2. Create an organisation and a brand

3. Configure your email settings (sector, style, CTA)

4. Create an API key from Settings → API keys

5. Send your first event

Authentication

All API requests require an API key passed in the X-API-Key header.

curl -X POST https://app.aitarax.com/api/v1/event/booking \
  -H "Content-Type: application/json" \
  -H "X-API-Key: atx_your_api_key_here" \
  -d '{...}'

Test events

Add "is_test": true to any event to mark it as a test. Test events are stored and visible in your dashboard but are never AI-processed, never billed, and are automatically deleted after 24 hours.

POST /api/v1/event/booking

{
  "identifier": "TEST-001",
  "start_at": "2026-04-15T10:00:00Z",
  "status": "completed",
  "is_test": true,
  "customer": {
    "email": "test@example.com",
    "name": "Test Customer"
  }
}

Tip: Use test events to verify your integration before going live. Any email address containing @example.com is automatically flagged as a test event.

Booking event

Send a booking event when an appointment is created, updated, or completed.

POST /api/v1/event/booking

{
  "identifier": "APT-2026-001",
  "start_at": "2026-04-15T10:00:00Z",
  "status": "completed",
  "status_at": "2026-04-15T11:30:00Z",
  "staff": "Sarah",
  "customer": {
    "email": "emma@example.com",
    "name": "Emma de Vries",
    "language": "nl",
    "timezone": "Europe/Amsterdam"
  },
  "items": [
    { "name": "Haircut", "quantity": 1 },
    { "name": "Colour treatment", "quantity": 1 }
  ]
}
FieldRequiredDescription
identifierRecommendedUnique ID from your system. Used for duplicate detection and status updates.
start_atRequired*When the appointment starts. ISO 8601. Falls back to datetime.
statusRecommendedCurrent status: scheduled, completed, cancelled, no-show.
status_atRecommendedWhen the status was set. Used for out-of-order import handling.
staffOptionalStaff member name. Included in AI context.
customerRequiredCustomer object. Must include email or identifier.
itemsOptionalArray of services. Included in AI context.
is_testOptionalMark as test event. Auto-deleted after 24 hours.

Order event

Send an order event when a purchase is placed or its status changes.

POST /api/v1/event/order

{
  "identifier": "ORD-2026-1001",
  "ordered_at": "2026-04-10T14:00:00Z",
  "status": "delivered",
  "status_at": "2026-04-12T16:00:00Z",
  "customer": {
    "email": "bakkerij@example.com",
    "name": "Noord Bakkerij BV",
    "identifier": "CUST-NB-002",
    "identifier_source": "erp"
  },
  "items": [
    { "name": "Tarwebloem 25kg", "quantity": 40 },
    { "name": "Suiker fijn 25kg", "quantity": 20 }
  ]
}

Customer fields

The customer object is the same across all event types. Customers are upserted on every event — fields are updated if they change.

FieldRequiredDescription
emailRequired*Customer email. Used for sending and deduplication.
nameRecommendedFull name or company name. Used in AI-generated emails.
date_birthOptionalDate of birth. ISO 8601 date (e.g. 1990-05-15). Used in AI context.
phoneOptionalPhone number in E.164 format (e.g. +31612345678).
languageOptionalISO 639-1 code (e.g. nl, en, fr). AI generates the email in this language.
timezoneOptionalIANA timezone (e.g. Europe/Amsterdam). Used for optimal send timing.
identifierOptionalExternal customer ID from your system. Use with identifier_source.
identifier_sourceOptionalSystem that issued the identifier (e.g. shopify, erp, crm).
tagsOptionalArray of strings for segmentation (e.g. ["vip", "wholesale"]).
segmentOptionalPrimary segment label (e.g. wholesale_nl). Used in AI context.
is_subscribedOptionalSubscription status. Set to false to suppress all emails for this customer.
url_paramsOptionalCustom URL parameters appended to links in emails. Scoped per event type (booking, order).

Batch overview

Batch endpoints let you send up to 100 records in a single API call. Use them for historical imports, nightly syncs, or any situation where you have multiple records to process at once.

EndpointBatch sizeUse case
POST /api/v1/event/booking/batch1–100Import historical bookings or sync multiple appointments at once.
POST /api/v1/event/order/batch1–100Import historical orders or sync multiple purchases at once.
POST /api/v1/customer/batch1–100Import or update customer records without sending an event.

The process_from parameter

Both booking and order batch endpoints accept an optional process_from date. Events before this date are stored for AI context but are not processed for email sending and are not billed. Events on or after this date go through the full pipeline and are billed normally.

POST /api/v1/event/booking/batch

{
  "process_from": "2025-01-01T00:00:00Z",
  "events": [
    {
      "identifier": "APT-2023-001",
      "start_at": "2023-06-10T10:00:00Z",
      ...
    },
    {
      "identifier": "APT-2025-088",
      "start_at": "2025-03-15T10:00:00Z",
      ...
    }
  ]
}

In this example, the 2023 event is stored as historical context only — no email is sent and it is not billed. The 2025 event goes through the full pipeline and is billed.

Choose process_from carefully. The AI uses all stored events — including historical ones — to understand each customer's behaviour and purchase patterns. If process_from is set too recently, the AI may only see a partial picture. For example, a customer who alternates between two products every year will appear to only buy one product if the window is too narrow. As a rule of thumb, set process_from at least 1–2 full purchase cycles before the date you want emails to start.

Response format

All batch endpoints return the same response shape. Partial success is possible — records that fail validation are listed in errors while valid records are still processed.

{
  "created": 85,
  "updated": 12,
  "errors": [
    {
      "index": 3,
      "message": "customer.email is required"
    }
  ]
}

Note: The index in each error refers to the zero-based position of the record in your request array. Always check the errors array even on a 200 response.

Batch bookings

Send up to 100 booking events in a single request. Each event in the array follows the same structure as a single booking event. Use the optional process_from parameter to split historical context from billable events.

POST /api/v1/event/booking/batch

{
  "process_from": "2025-01-01T00:00:00Z",
  "events": [
    {
      "identifier": "APT-2026-001",
      "start_at": "2026-04-15T10:00:00Z",
      "status": "completed",
      "status_at": "2026-04-15T11:30:00Z",
      "staff": "Sarah",
      "is_test": false,
      "customer": {
        "email": "emma@example.com",
        "name": "Emma de Vries",
        "language": "nl",
        "timezone": "Europe/Amsterdam",
        "identifier": "cust_abc123",
        "identifier_source": "shopify",
        "is_subscribed": true
      },
      "items": [
        { "name": "Haircut", "quantity": 1 }
      ]
    },
    {
      "identifier": "APT-2026-002",
      "start_at": "2026-04-15T14:00:00Z",
      "status": "completed",
      "status_at": "2026-04-15T15:00:00Z",
      "staff": "Tom",
      "customer": {
        "email": "jan@example.com",
        "name": "Jan Bakker"
      },
      "items": [
        { "name": "Beard trim", "quantity": 1 }
      ]
    }
  ]
}

Tip: For historical imports, always include status_at so Aitarax can handle out-of-order records correctly. Use "is_test": true on all records while verifying your import.

Batch orders

Send up to 100 order events in a single request. Uses ordered_at instead of start_at. Supports the same optional process_from parameter as batch bookings.

POST /api/v1/event/order/batch

{
  "process_from": "2025-01-01T00:00:00Z",
  "events": [
    {
      "identifier": "ORD-2026-1001",
      "ordered_at": "2026-04-10T14:00:00Z",
      "status": "delivered",
      "status_at": "2026-04-12T16:00:00Z",
      "is_test": false,
      "customer": {
        "email": "bakkerij@example.com",
        "name": "Noord Bakkerij BV",
        "identifier": "CUST-NB-002",
        "identifier_source": "erp",
        "is_subscribed": true
      },
      "items": [
        { "name": "Tarwebloem 25kg", "quantity": 40 },
        { "name": "Suiker fijn 25kg", "quantity": 20 }
      ]
    }
  ]
}

Common use case: Nightly sync from your ERP or webshop. Query orders updated since your last sync and send the full batch in one call. The identifier field ensures duplicates are updated rather than re-created.

Batch customers

Import or update customer records without attaching an event. Useful for syncing your full customer base before sending events, or for updating subscription status and segments in bulk.

POST /api/v1/customer/batch

{
  "customers": [
    {
      "email": "jane@example.com",
      "name": "Jane Doe",
      "date_birth": "1990-05-15",
      "phone": "+31612345678",
      "language": "en",
      "timezone": "America/Chicago",
      "identifier": "cust_abc123",
      "identifier_source": "shopify",
      "is_subscribed": true,
      "url_params": {
        "booking": {
          "customer_id": "C123",
          "utm_campaign": "followup",
          "utm_source": "email"
        },
        "order": {
          "customer_id": "C123",
          "discount_code": "SAVE10"
        }
      }
    }
  ]
}
FieldRequiredDescription
emailRequired*Customer email. Primary key for upsert.
nameRecommendedFull name or company name.
date_birthOptionalISO 8601 date (e.g. 1990-05-15).
phoneOptionalE.164 format (e.g. +31612345678).
languageOptionalISO 639-1 code. Used for AI email generation.
timezoneOptionalIANA timezone. Used for optimal send timing.
identifierOptionalExternal ID. Use with identifier_source.
identifier_sourceOptionalSystem that issued the identifier (e.g. shopify, erp).
is_subscribedOptionalSet to false to suppress all emails for this customer.
url_paramsOptionalCustom URL parameters for email links. Scoped per event type.

Note: Customer batch does not trigger any AI processing or email sends. It only creates or updates customer records. To trigger re-engagement emails, send events via the booking or order batch endpoints.

n8n

Connect Aitarax to any app using n8n's HTTP Request node. Works with n8n Cloud and self-hosted instances.

Step 1 — Store your API key as a credential

In n8n, go to Credentials → New → Header Auth. Set the name to X-API-Key and the value to your Aitarax API key. Save it as Aitarax API.

Step 2 — Add an HTTP Request node

Add an HTTP Request node to your workflow and configure it as follows:

Method:      POST
URL:         https://app.aitarax.com/api/v1/event/booking
Auth:        Header Auth → Aitarax API
Body type:   JSON

Body:
{
  "identifier": "{{ $json.booking_id }}",
  "start_at":   "{{ $json.start_time }}",
  "status":     "{{ $json.status }}",
  "status_at":  "{{ $json.updated_at }}",
  "staff":      "{{ $json.staff_name }}",
  "customer": {
    "email":    "{{ $json.customer_email }}",
    "name":     "{{ $json.customer_name }}",
    "language": "{{ $json.customer_language }}",
    "timezone": "{{ $json.customer_timezone }}"
  },
  "items": [
    { "name": "{{ $json.service_name }}", "quantity": 1 }
  ]
}

Step 3 — Test with a test event

Add "is_test": true to your body while testing. The event will appear in your Aitarax dashboard and be automatically deleted after 24 hours.

For order events

Change the URL to /api/v1/event/order and replace start_at with ordered_at.

Method:      POST
URL:         https://app.aitarax.com/api/v1/event/order

Body:
{
  "identifier":  "{{ $json.order_id }}",
  "ordered_at":  "{{ $json.created_at }}",
  "status":      "{{ $json.fulfillment_status }}",
  "status_at":   "{{ $json.updated_at }}",
  "customer": {
    "email":     "{{ $json.customer_email }}",
    "name":      "{{ $json.customer_name }}"
  },
  "items": {{ $json.line_items.map(i => ({ name: i.title, quantity: i.quantity })) }}
}

Batch imports with n8n

Use the Schedule trigger and an Aggregate node to collect records and send them as a batch to /api/v1/event/booking/batch. The body must wrap your events in an events array (or customers for customer batch).

Method:      POST
URL:         https://app.aitarax.com/api/v1/event/booking/batch
Auth:        Header Auth → Aitarax API
Body type:   JSON

Body:
{
  "events": {{ $json.all_bookings }}
}

Common triggers: Use n8n's Webhook node to receive events in real time, or the Schedule node to batch-sync from your database at regular intervals. Both work well with Aitarax.

Zapier

Send events to Aitarax from any Zapier trigger using the Webhooks by Zapier action. No custom app needed.

Step 1 — Create a new Zap

Choose any trigger that fires when a booking or order is created or updated — for example Calendly → Invitee Created, Shopify → New Order, or Google Calendar → Event Started.

Step 2 — Add a Webhooks by Zapier action

Search for Webhooks by Zapier and select the POST action. Configure it as follows:

FieldValue
URLhttps://app.aitarax.com/api/v1/event/booking
Payload TypeJSON
Headers — NameX-API-Key
Headers — Valueatx_your_api_key_here

Step 3 — Map the data fields

In the Data section, map your trigger fields to the Aitarax event structure. Example for a booking:

identifier           → [Booking ID from trigger]
start_at             → [Appointment Start Time]
status               → completed
status_at            → [Updated At]
staff                → [Staff Name]
customer__email      → [Customer Email]
customer__name       → [Customer Name]
customer__language   → nl
items__0__name       → [Service Name]
items__0__quantity   → 1

Note: Zapier uses double underscores (__) to represent nested JSON. So customer__email maps to {"customer": {"email": "..."}}.

Step 4 — Test the Zap

Before turning on your Zap, add is_test → true to your data fields and run a test. Check your Aitarax Events page to confirm the event arrived. Then remove is_test and publish.

Common Zapier triggers: Calendly (bookings), Shopify (orders), WooCommerce (orders), Acuity Scheduling (appointments), Mindbody (classes), Square (payments), and any app with a Zapier integration.

Make

Send events to Aitarax from Make (formerly Integromat) using the HTTP → Make a request module. Supports both real-time webhooks and scheduled batch syncs.

Step 1 — Create a new scenario

Add a trigger module for your source app — for example Calendly → Watch Events, Shopify → Watch Orders, or Webhooks → Custom webhook for real-time updates.

Step 2 — Add an HTTP module

Add the HTTP → Make a request module and configure it as follows:

SettingValue
URLhttps://app.aitarax.com/api/v1/event/booking
MethodPOST
Body typeRaw
Content typeapplication/json
Header — NameX-API-Key
Header — Valueatx_your_api_key_here

Step 3 — Build the request body

In the Request content field, paste the JSON body and map your trigger data using Make's variable picker ( button):

{
  "identifier": "{{1.booking_id}}",
  "start_at":   "{{1.start_time}}",
  "status":     "{{1.status}}",
  "status_at":  "{{1.updated_at}}",
  "staff":      "{{1.staff_name}}",
  "customer": {
    "email":    "{{1.customer.email}}",
    "name":     "{{1.customer.name}}",
    "language": "{{1.customer.language}}",
    "timezone": "{{1.customer.timezone}}"
  },
  "items": [
    {
      "name":     "{{1.service_name}}",
      "quantity": 1
    }
  ]
}

Step 4 — Handle multiple items

If your source app returns multiple line items, use Make's Iterator module before the HTTP module to loop through items and send one event per booking/order with all items included.

Step 5 — Test and activate

Add "is_test": true to your request body and run the scenario once. Verify the event appears in your Aitarax Events page, then remove is_test and activate the scenario.

Common Make triggers: Shopify, WooCommerce, Calendly, Acuity Scheduling, Google Sheets (for batch imports), Airtable, and any app with a Make integration or webhook support.

Rate limits

Each API key is rate limited per organisation. All three windows apply simultaneously — a request must pass all three.

WindowLimitPurpose
Per minute200 requestsAllows batch imports, blocks runaway loops
Per hour5,000 requestsHandles flash sales and high-volume periods
Per day50,000 requestsHigh-volume e-commerce ceiling

Batch and rate limits: Each batch request counts as 1 request against your rate limit, regardless of how many records it contains. Sending 100 events in one batch call is far more efficient than 100 individual calls.

Rate limit headers are included in every response: X-RateLimit-Remaining-Minute, X-RateLimit-Remaining-Hour, X-RateLimit-Remaining-Day. When a limit is exceeded, the API returns HTTP 429 with a Retry-After header.

Error codes

CodeMeaning
200Success. Event created or duplicate detected. For batch requests, check the errors array for partial failures.
400Bad request. Missing required field or invalid value.
401Unauthorized. Missing or invalid API key.
429Rate limit exceeded. Check Retry-After header.
500Internal server error. Contact support.