📚 DatomniX Documentation

← Back to Index

Server-to-Server (S2S) Integration Guide

Overview

DatomniX provides a powerful Server-to-Server API that gives you complete control over event tracking, including custom product categorization for ANY industry.

Key Feature: Send your own custom product categories/verticals - no restrictions, 100% flexible!

---

Authentication

Use your Brand Private Key (available in Dashboard → Pixel Setup).

const BRAND_PRIVATE_KEY = 'your-brand-private-key-here';

---

Endpoint

POST https://api.datomnix.com/api/v1/api/events
Content-Type: application/json

---

Basic Event Structure

{
  "brand_private_key": "YOUR_BRAND_PRIVATE_KEY",
  "event_id": "unique-idempotent-id",
  "event_name": "purchase",
  "timestamp": "2025-11-16T10:30:00.000Z",
  "session_id": "sess_abc123",
  "user_id": "user_12345",
  "email": "customer@example.com",
  "transaction_id": "ORDER-12345",
  "value": 149.99,
  "currency": "USD",
  "items": [
    {
      "id": "prod_001",
      "name": "Premium Product",
      "price": 99.99,
      "quantity": 1,
      "vertical": "YOUR_CUSTOM_CATEGORY"
    }
  ]
}

---

Product Categorization - YOUR CHOICE!

You have complete freedom to define your product taxonomy. Send whatever categories make sense for YOUR business:

Option 1: Custom Vertical Field (Recommended)

The vertical field is YOUR custom classification - define it however you want!

Examples by Industry:

#

E-Commerce (Fashion)


{
  "id": "prod_001",
  "name": "Men's Running Shoes",
  "vertical": "MENS_FOOTWEAR",
  "verticals": ["ATHLETIC", "MENS_FOOTWEAR"],
  "category": "Shoes",
  "tags": ["running", "athletic", "nike"]
}

#

SaaS


{
  "id": "sub_001",
  "name": "Enterprise Plan",
  "vertical": "SUBSCRIPTION",
  "verticals": ["SUBSCRIPTION", "ENTERPRISE"],
  "category": "Software License",
  "tags": ["annual", "enterprise", "unlimited"]
}

#

Telehealth


{
  "id": "prod_001",
  "name": "Weight Loss Program",
  "vertical": "WEIGHT_LOSS",
  "verticals": ["WEIGHT_LOSS", "TELEHEALTH"],
  "category": "Treatment Plans",
  "tags": ["semaglutide", "ozempic", "weight-loss"]
}

#

B2B Services


{
  "id": "service_001",
  "name": "Marketing Consultation",
  "vertical": "CONSULTING",
  "verticals": ["CONSULTING", "MARKETING"],
  "category": "Professional Services",
  "tags": ["hourly", "marketing", "strategy"]
}

#

Education


{
  "id": "course_001",
  "name": "Python Bootcamp",
  "vertical": "ONLINE_COURSES",
  "verticals": ["ONLINE_COURSES", "PROGRAMMING"],
  "category": "Education",
  "tags": ["python", "bootcamp", "beginner"]
}

#

Real Estate


{
  "id": "prop_001",
  "name": "Downtown Condo",
  "vertical": "RESIDENTIAL",
  "verticals": ["RESIDENTIAL", "CONDO"],
  "category": "Property",
  "tags": ["2br", "downtown", "waterfront"]
}

Option 2: Platform Categories

Use your e-commerce platform's native categories:

{
  "category": "Electronics",
  "categories": ["Electronics", "Computers", "Laptops"]
}

Option 3: Tags

Use flexible tagging:

{
  "tags": ["premium", "bestseller", "new-arrival", "limited-edition"]
}

Option 4: Combine All Three!

{
  "id": "prod_001",
  "name": "Premium Gaming Laptop",
  "vertical": "HIGH_TICKET_ELECTRONICS",
  "verticals": ["HIGH_TICKET_ELECTRONICS", "GAMING"],
  "category": "Laptops",
  "categories": ["Electronics", "Computers", "Laptops", "Gaming"],
  "tags": ["rtx-4090", "premium", "gaming", "high-performance"]
}

---

Complete Product Item Schema

interface EventItem {
  // Required
  id: string;              // Your product ID
  name: string;            // Product name
  price: number;           // Unit price
  quantity: number;        // Quantity purchased
  
  // Custom Classification (YOUR CHOICE!)
  vertical?: string;       // YOUR primary custom category
  verticals?: string[];    // Multiple custom categories
  
  // Platform Categories
  category?: string;       // Primary platform category
  categories?: string[];   // All platform categories
  
  // Additional Classification
  tags?: string[];         // Flexible product tags
  sku?: string;            // SKU code
  brand?: string;          // Product brand
  variant?: string;        // Product variant
  
  // Attributes & Metadata
  attributes?: {           // Structured attributes
    size?: string;
    color?: string;
    material?: string;
    [key: string]: any;
  };
  metadata?: {             // Any custom data
    [key: string]: any;
  };
  
  // Currency (optional, inherits from event)
  currency?: string;
}

---

Full Integration Examples

Example 1: Node.js (E-Commerce Purchase)

const axios = require('axios');

async function trackPurchase(order) {
  try {
    const response = await axios.post('https://api.datomnix.com/api/v1/api/events', {
      // Authentication
      brand_private_key: process.env.DATOMNIX_PRIVATE_KEY,
      
      // Event Details
      event_id: `order_${order.id}`,
      event_name: 'purchase',
      timestamp: new Date().toISOString(),
      session_id: order.session_id,
      
      // Customer Info
      user_id: order.customer_id,
      email: order.customer_email,
      phone: order.customer_phone,
      
      // Transaction Details
      transaction_id: order.id,
      value: order.total,
      currency: 'USD',
      
      // Products with YOUR custom categories
      items: order.line_items.map(item => ({
        id: item.product_id,
        name: item.product_name,
        sku: item.sku,
        price: item.price,
        quantity: item.quantity,
        
        // YOUR CUSTOM VERTICALS (define as you wish!)
        vertical: item.custom_category,           // e.g., "MENS_APPAREL"
        verticals: item.custom_categories,        // e.g., ["MENS_APPAREL", "PREMIUM"]
        
        // Platform categories
        category: item.category,
        categories: item.all_categories,
        
        // Tags
        tags: item.tags,
        
        // Custom attributes
        attributes: {
          size: item.variant_size,
          color: item.variant_color,
        },
      })),
      
      // UTM Tracking
      utm_source: order.utm_source,
      utm_medium: order.utm_medium,
      utm_campaign: order.utm_campaign,
      
      // Additional Context
      properties: {
        payment_method: order.payment_method,
        shipping_method: order.shipping_method,
        discount_code: order.discount_code,
      },
    });
    
    console.log('✅ Purchase tracked:', response.data);
  } catch (error) {
    console.error('❌ Failed to track purchase:', error.response?.data || error.message);
  }
}

// Example usage
await trackPurchase({
  id: 'ORDER-12345',
  customer_id: 'CUST-789',
  customer_email: 'john@example.com',
  session_id: 'sess_abc123',
  total: 249.98,
  line_items: [
    {
      product_id: 'PROD-001',
      product_name: 'Premium Running Shoes',
      sku: 'SHOE-RUN-001',
      price: 129.99,
      quantity: 1,
      custom_category: 'ATHLETIC_FOOTWEAR',        // YOUR custom vertical!
      custom_categories: ['ATHLETIC_FOOTWEAR', 'MENS'],
      category: 'Footwear',
      all_categories: ['Footwear', 'Athletic', 'Mens'],
      tags: ['running', 'premium', 'nike'],
      variant_size: '10',
      variant_color: 'Black',
    },
    {
      product_id: 'PROD-002',
      product_name: 'Sports Water Bottle',
      sku: 'BOTTLE-001',
      price: 19.99,
      quantity: 1,
      custom_category: 'ACCESSORIES',               // YOUR custom vertical!
      custom_categories: ['ACCESSORIES', 'ATHLETIC'],
      category: 'Accessories',
      all_categories: ['Accessories', 'Hydration'],
      tags: ['athletic', 'water-bottle'],
    },
  ],
  utm_source: 'google',
  utm_medium: 'cpc',
  utm_campaign: 'summer-sale',
  payment_method: 'credit_card',
  shipping_method: 'express',
});

Example 2: Python (SaaS Subscription)

import requests
import os
from datetime import datetime
import uuid

def track_subscription(subscription):
    """Track a SaaS subscription event"""
    
    payload = {
        # Authentication
        "brand_private_key": os.getenv("DATOMNIX_PRIVATE_KEY"),
        
        # Event Details
        "event_id": f"sub_{subscription['id']}",
        "event_name": "purchase",
        "timestamp": datetime.utcnow().isoformat() + "Z",
        "session_id": subscription['session_id'],
        
        # Customer Info
        "user_id": subscription['user_id'],
        "email": subscription['user_email'],
        
        # Transaction Details
        "transaction_id": subscription['id'],
        "value": subscription['amount'],
        "currency": "USD",
        
        # Products with YOUR custom categories
        "items": [{
            "id": subscription['plan_id'],
            "name": subscription['plan_name'],
            "price": subscription['amount'],
            "quantity": 1,
            
            # YOUR CUSTOM VERTICALS!
            "vertical": "SUBSCRIPTION",
            "verticals": ["SUBSCRIPTION", subscription['plan_tier'].upper()],
            
            # Platform categories
            "category": "Software License",
            "categories": ["Software", "Subscription"],
            
            # Tags
            "tags": [
                subscription['billing_cycle'],  # "monthly", "annual"
                subscription['plan_tier'],      # "starter", "pro", "enterprise"
                "saas"
            ],
            
            # Custom attributes
            "attributes": {
                "billing_cycle": subscription['billing_cycle'],
                "plan_tier": subscription['plan_tier'],
                "seats": subscription['seats'],
            },
            
            # Metadata
            "metadata": {
                "trial_days": subscription.get('trial_days'),
                "is_upgrade": subscription.get('is_upgrade', False),
            }
        }],
        
        # UTM Tracking
        "utm_source": subscription.get('utm_source'),
        "utm_medium": subscription.get('utm_medium'),
        "utm_campaign": subscription.get('utm_campaign'),
        
        # Additional Context
        "properties": {
            "billing_cycle": subscription['billing_cycle'],
            "plan_tier": subscription['plan_tier'],
            "is_trial": subscription.get('is_trial', False),
        }
    }
    
    try:
        response = requests.post(
        'https://api.datomnix.com/api/v1/api/events',
            json=payload,
            headers={'Content-Type': 'application/json'}
        )
        response.raise_for_status()
        print(f"✅ Subscription tracked: {response.json()}")
        return response.json()
    except requests.exceptions.RequestException as e:
        print(f"❌ Failed to track subscription: {e}")
        raise

# Example usage
track_subscription({
    'id': 'SUB-12345',
    'user_id': 'USER-789',
    'user_email': 'company@example.com',
    'session_id': 'sess_xyz789',
    'plan_id': 'PLAN-ENTERPRISE',
    'plan_name': 'Enterprise Plan',
    'plan_tier': 'enterprise',
    'amount': 499.00,
    'billing_cycle': 'annual',
    'seats': 50,
    'trial_days': 0,
    'is_upgrade': True,
    'utm_source': 'linkedin',
    'utm_medium': 'paid',
    'utm_campaign': 'enterprise-q4',
})

Example 3: PHP (WordPress/WooCommerce)

<?php

function track_woocommerce_order($order_id) {
    $order = wc_get_order($order_id);
    
    // Prepare line items with YOUR custom categories
    $items = [];
    foreach ($order->get_items() as $item) {
        $product = $item->get_product();
        
        $items[] = [
            'id' => $product->get_id(),
            'name' => $item->get_name(),
            'sku' => $product->get_sku(),
            'price' => (float) $item->get_total() / $item->get_quantity(),
            'quantity' => $item->get_quantity(),
            
            // YOUR CUSTOM VERTICALS (from product meta or custom taxonomy)
            'vertical' => get_post_meta($product->get_id(), '_custom_vertical', true) ?: 'GENERAL',
            'verticals' => wp_get_post_terms($product->get_id(), 'custom_category', ['fields' => 'names']),
            
            // Platform categories
            'category' => $product->get_category_ids() ? get_term($product->get_category_ids()[0])->name : null,
            'categories' => wp_get_post_terms($product->get_id(), 'product_cat', ['fields' => 'names']),
            
            // Tags
            'tags' => wp_get_post_terms($product->get_id(), 'product_tag', ['fields' => 'names']),
            
            // Attributes
            'attributes' => [
                'weight' => $product->get_weight(),
                'dimensions' => [
                    'length' => $product->get_length(),
                    'width' => $product->get_width(),
                    'height' => $product->get_height(),
                ],
            ],
        ];
    }
    
    $payload = [
        // Authentication
        'brand_private_key' => get_option('datomnix_private_key'),
        
        // Event Details
        'event_id' => 'order_' . $order_id,
        'event_name' => 'purchase',
        'timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
        'session_id' => $order->get_customer_id() ? 'user_' . $order->get_customer_id() : 'sess_' . wp_generate_uuid4(),
        
        // Customer Info
        'user_id' => $order->get_customer_id() ?: null,
        'email' => $order->get_billing_email(),
        'phone' => $order->get_billing_phone(),
        
        // Transaction Details
        'transaction_id' => $order->get_order_number(),
        'value' => (float) $order->get_total(),
        'currency' => $order->get_currency(),
        
        // Products with YOUR custom categories
        'items' => $items,
        
        // UTM Tracking
        'utm_source' => $order->get_meta('_utm_source'),
        'utm_medium' => $order->get_meta('_utm_medium'),
        'utm_campaign' => $order->get_meta('_utm_campaign'),
        
        // Additional Context
        'properties' => [
            'payment_method' => $order->get_payment_method(),
            'shipping_method' => $order->get_shipping_method(),
            'coupon_code' => implode(',', $order->get_coupon_codes()),
        ],
    ];
    
    $response = wp_remote_post('https://api.datomnix.com/api/v1/api/events', [
        'headers' => ['Content-Type' => 'application/json'],
        'body' => json_encode($payload),
        'timeout' => 15,
    ]);
    
    if (is_wp_error($response)) {
        error_log('DatomniX tracking failed: ' . $response->get_error_message());
        return false;
    }
    
    $body = json_decode(wp_remote_retrieve_body($response), true);
    error_log('DatomniX tracking success: ' . print_r($body, true));
    return true;
}

// Hook into WooCommerce
add_action('woocommerce_order_status_completed', 'track_woocommerce_order');

---

Batch Event Ingestion

Send up to 100 events in a single request:

const axios = require('axios');

await axios.post('https://api.datomnix.com/api/v1/api/events/batch', {
  brand_private_key: process.env.DATOMNIX_PRIVATE_KEY,
  events: [
    {
      event_id: 'evt_001',
      event_name: 'purchase',
      timestamp: '2025-11-16T10:00:00Z',
      session_id: 'sess_abc',
      transaction_id: 'ORDER-001',
      value: 99.99,
      currency: 'USD',
      items: [
        {
          id: 'prod_001',
          name: 'Product A',
          price: 99.99,
          quantity: 1,
          vertical: 'YOUR_CATEGORY_1',  // YOUR custom vertical!
        }
      ]
    },
    {
      event_id: 'evt_002',
      event_name: 'purchase',
      timestamp: '2025-11-16T10:05:00Z',
      session_id: 'sess_xyz',
      transaction_id: 'ORDER-002',
      value: 149.99,
      currency: 'USD',
      items: [
        {
          id: 'prod_002',
          name: 'Product B',
          price: 149.99,
          quantity: 1,
          vertical: 'YOUR_CATEGORY_2',  // YOUR custom vertical!
        }
      ]
    },
  ]
});

Reading the batch response

A batch can partly succeed, and the response says so per event. Do not
treat a 2xx as "all 100 events are in". Until 2026-08-15 this endpoint
answered 200 {success: true} for every request it accepted, including for
events that failed to reach the queue and were therefore never going to be
processed. A client had no way to know, so it never resent them and they
were simply lost.

{
  "success": false,
  "events_submitted": 3,
  "events_processed": 2,
  "event_ids": ["evt_001", "evt_003"],
  "results": [
    { "event_id": "evt_001", "success": true },
    { "event_id": "evt_002", "success": false, "reason": "validation",     "error": "Invalid or inactive brand" },
    { "event_id": "evt_003", "success": true }
  ]
}

success is true only when every submitted event was queued. results
carries one entry per submitted event, and reason tells you what to do
about a failure:

| reason | Meaning | What to do |
|---|---|---|
| validation | This event's payload (or the brand) was rejected | Fix the event. Resending it unchanged fails identically |
| publish_failed | The event was valid but could not reach the queue | Resend it. This is our fault, not yours |

The status code carries the same distinction, so a client that only checks
for 2xx still gets an honest signal:

| Status | Meaning |
|---|---|
| 200 | Every event was queued |
| 207 | Some were queued and some were not. Read results |
| 400 | Nothing was queued, and every failure was a payload problem |
| 402 | Plan ingest limit reached. No further event in the batch would have succeeded either |
| 502 | Nothing was queued, but at least one event was valid. Retry the whole batch |

Retry only the events whose results entry says publish_failed.
Resending the whole batch is safe (ingestion is idempotent on event_id)
but wasteful.

---

Best Practices

1. Define Your Taxonomy

Create a consistent categorization system for your business:

// ✅ Good: Consistent, hierarchical
const VERTICALS = {
  MENS_APPAREL: 'MENS_APPAREL',
  WOMENS_APPAREL: 'WOMENS_APPAREL',
  ACCESSORIES: 'ACCESSORIES',
  PREMIUM: 'PREMIUM',
  BUDGET: 'BUDGET',
};

// ❌ Bad: Inconsistent naming
const categories = ['mens', 'Women_Apparel', 'ACCESSORIES', 'premium items'];

2. Use Multiple Classification Levels

Combine vertical, categories, and tags for rich attribution:

{
  vertical: "PREMIUM_ELECTRONICS",           // YOUR custom high-level category
  verticals: ["PREMIUM_ELECTRONICS", "LAPTOPS"],
  category: "Laptops",                       // Platform category
  categories: ["Electronics", "Computers", "Laptops"],
  tags: ["gaming", "rtx-4090", "premium"]    // Flexible tags
}

3. Idempotent Event IDs

Always use unique, deterministic event IDs to prevent duplicates:

// ✅ Good: Deterministic, includes timestamp
const event_id = `purchase_${order.id}_${Date.now()}`;

// ❌ Bad: Random, can cause duplicates
const event_id = Math.random().toString();

4. Include UTM Parameters

Always pass UTM data for accurate attribution:

{
  utm_source: order.utm_source || 'direct',
  utm_medium: order.utm_medium || 'none',
  utm_campaign: order.utm_campaign,
  utm_content: order.utm_content,
  utm_term: order.utm_term,
}

5. Error Handling

Implement retry logic for failed requests:

async function trackWithRetry(payload, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      const response = await axios.post(
        'https://api.datomnix.com/api/events',
        payload,
        { timeout: 5000 }
      );
      return response.data;
    } catch (error) {
      if (i === retries - 1) throw error;
      await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
    }
  }
}

---

Required Fields

| Field | Type | Description |
|-------|------|-------------|
| brand_private_key | string | Your brand private key (from dashboard) |
| event_id | string | Unique, idempotent event identifier |
| event_name | string | Event type (purchase, page_view, add_to_cart, etc.) |
| timestamp | string | ISO 8601 timestamp |
| session_id | string | Session identifier |

---

Optional But Recommended

| Field | Type | Description |
|-------|------|-------------|
| user_id | string | Your internal user ID |
| email | string | Customer email (hashed for privacy) |
| transaction_id | string | Order/transaction ID (for purchase events) |
| value | number | Transaction value |
| currency | string | ISO currency code (USD, EUR, etc.) |
| items | array | Products with YOUR custom categories |
| utm_* | string | UTM parameters for attribution |

---

Event Types

Standard event names (or use your own):

---

Built by ETK Technologies © 2025