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.
metadataOptionalFree-form JSON object with additional context. Passed to the AI and used for communication type routing.
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 }
  ]
}
FieldRequiredDescription
identifierRecommendedUnique ID from your system. Used for duplicate detection and status updates.
ordered_atRequired*When the order was placed. ISO 8601. Falls back to datetime.
statusRecommendedCurrent status: pending, processing, delivered, cancelled, refunded.
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 products or services. Included in AI context.
metadataOptionalFree-form JSON object with additional context. Passed to the AI and used for communication type routing.
is_testOptionalMark as test event. Auto-deleted after 24 hours.

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.

Ready-made templates

Download and import these workflow templates directly into your n8n instance to get started quickly.

PostgreSQL sync

Incrementally sync customers, bookings and orders from any PostgreSQL database using a watermark system.

href="https://github.com/geerttib/aitarax-n8n-templates/blob/main/aitarax-postgresql-sync.json" target="_blank" rel="noopener noreferrer" className="shrink-0 ml-4 text-xs font-medium px-3 py-1.5 rounded-lg border border-gray-200 text-gray-600 hover:bg-gray-50 transition"Download →

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
metadata__communicationType   → [Event Type, e.g. VERGUNNING_VERLOOPT]
metadata__project             → [Project Name]

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

Communication type routing: Als je Aitarax wilt laten reageren op specifieke event types (zoals een vergunning die verloopt of een bezwaartermijn), voeg dan metadata__communicationType toe met een waarde die overeenkomt met een geconfigureerde mapping in je Aitarax brand settings. Zorg dat je eerst de bijbehorende mapping aanmaakt onder Email Settings → Communication type routing.

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.

Event fields

Complete reference of all fields accepted by the booking and order event endpoints. Fields marked with * require at least one of the options listed.

Booking event fields

FieldTypeRequiredDescription
identifierstringRecommendedUnique ID from your system. Used for duplicate detection and status updates.
start_atISO 8601Required*When the appointment starts. Falls back to datetime if omitted.
datetimeISO 8601Required*Fallback datetime field. Use start_at when possible.
statusstringRecommendedCurrent status: scheduled, completed, cancelled, no-show.
status_atISO 8601RecommendedWhen the status was set. Used for out-of-order import handling.
staffstringOptionalStaff member name. Included in AI context if AI mention staff is enabled.
customerobjectRequiredCustomer object. Must include email or identifier. See Customer fields.
itemsarrayOptionalArray of services rendered. Each item has name and quantity.
metadataobjectOptionalFree-form JSON object. Passed to the AI and used for communication type routing.
is_testbooleanOptionalMark as test event. Never billed, auto-deleted after 24 hours.

Order event fields

FieldTypeRequiredDescription
identifierstringRecommendedUnique ID from your system. Used for duplicate detection and status updates.
ordered_atISO 8601Required*When the order was placed. Falls back to datetime if omitted.
datetimeISO 8601Required*Fallback datetime field. Use ordered_at when possible.
statusstringRecommendedCurrent status: pending, processing, delivered, cancelled, refunded.
status_atISO 8601RecommendedWhen the status was set. Used for out-of-order import handling.
staffstringOptionalStaff member name. Included in AI context if AI mention staff is enabled.
customerobjectRequiredCustomer object. Must include email or identifier. See Customer fields.
itemsarrayOptionalArray of products ordered. Each item has name and quantity.
metadataobjectOptionalFree-form JSON object. Passed to the AI and used for communication type routing.
is_testbooleanOptionalMark as test event. Never billed, auto-deleted after 24 hours.

Item fields

Each object in the items array accepts the following fields:

FieldTypeRequiredDescription
namestringRequiredName of the service or product. Included in AI context.
quantitynumberOptionalQuantity. Defaults to 1 if omitted.

Communication type routing

Add a communicationType key to your event's metadata to trigger a specific email purpose and prompt instead of the brand default re-engagement flow.

This is useful for sectors like property management, automotive, or healthcare where events have distinct communication purposes — payment reminders, maintenance updates, meeting announcements, and so on.

How it works

1. Send an event with communicationType in the metadata

2. In your brand's Email Settings → Communication type routing, add a mapping for that type

3. Set the email purpose (Re-engagement, Informative, or Check-up) and optionally a prompt version

4. Aitarax uses that mapping instead of the brand default for matching events

Example

POST /api/v1/event/booking

{
  "identifier": "ALV-2026-06",
  "start_at": "2026-06-15T19:30:00Z",
  "status": "scheduled",
  "customer": {
    "identifier": "owner_abc",
    "identifier_source": "vve_admin"
  },
  "metadata": {
    "communicationType": "ALV_AANKONDIGING",
    "vve_name": "VvE Parkstraat 12-24",
    "apartment": "Appartement 6C",
    "description": "Jaarlijkse Algemene Ledenvergadering 2026",
    "location": "Wijkcentrum De Brug, Amsterdam"
  }
}

Naming convention: The communicationType value must exactly match the value configured in your brand's Communication type routing settings. Use UPPERCASE with underscores — for example ALV_AANKONDIGING, REPARATIE_AFGEROND, or CONTRIBUTIE_HERINNERING.

Default behaviour

Events without a communicationType in their metadata always use the brand default — which is re-engagement unless you have changed it in Email Settings. No configuration needed for standard re-engagement use cases.

All metadata fields are passed to the AI

Every key in the metadata object is included in the AI context when generating the email. Use it to pass any structured data that should influence the email content — apartment numbers, meeting locations, invoice amounts, completed work descriptions, and so on.

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.

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.