{
  "openapi": "3.1.0",
  "info": {
    "title": "Tracklution Webhook API",
    "version": "1.0.0",
    "summary": "Server-to-server offline conversion ingestion for Tracklution.",
    "description": "Public webhook endpoint for sending conversion events from any backend, CRM, payment system, or no-code automation tool into Tracklution. Events are routed to every enabled ad-platform connector (Meta, Google Ads, TikTok, LinkedIn, Snapchat, Pinterest, Microsoft/Bing, Reddit, Klaviyo, GA4, CM360, Adform, custom webhooks) with platform-specific field shapes (SHA-256 hashed PII, click-ID forwarding, deduplication keys) handled automatically.",
    "contact": {
      "name": "Tracklution Support",
      "email": "support@tracklution.com",
      "url": "https://support.tracklution.com"
    },
    "license": {
      "name": "Tracklution Terms of Service",
      "url": "https://www.tracklution.com/policies/terms/"
    }
  },
  "servers": [
    {
      "url": "https://{trackingDomain}",
      "description": "Customer's first-party tracking subdomain (DNS CNAME to Tracklution). Configure via DNS CNAME `t.<yourdomain> -> <key>.cname-target.tracklution.com` in the Tracklution dashboard.",
      "variables": {
        "trackingDomain": {
          "default": "t.example.com"
        }
      }
    }
  ],
  "tags": [
    {
      "name": "Conversions",
      "description": "Server-to-server offline conversion ingestion."
    }
  ],
  "paths": {
    "/collect/hook": {
      "post": {
        "summary": "Send a conversion event",
        "description": "Submits a single conversion event to Tracklution. The event is fanned out to every enabled ad-platform connector for this tracking key. CORS is open (any origin); the only credential is the tracking key in the `k` query parameter.",
        "operationId": "collectHookPost",
        "tags": ["Conversions"],
        "parameters": [{ "$ref": "#/components/parameters/TrackingKey" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ConversionEvent" },
              "examples": {
                "purchase": {
                  "summary": "E-commerce purchase",
                  "value": {
                    "event": "Purchase",
                    "value": 99.99,
                    "currency": "EUR",
                    "email": "customer@example.com",
                    "phoneNumber": "+358501234567",
                    "firstName": "David",
                    "lastName": "Smith",
                    "order_id": "ORD-12345",
                    "source": "stripe-webhook"
                  }
                },
                "lead": {
                  "summary": "Lead-gen form submission",
                  "value": {
                    "event": "Lead",
                    "value": 50,
                    "currency": "EUR",
                    "email": "prospect@example.com",
                    "form_id": "request-quote",
                    "source": "hubspot-form"
                  }
                },
                "instant_delivery": {
                  "summary": "Bypass batch queue (Plus plans and above)",
                  "value": {
                    "event": "Purchase",
                    "value": 250,
                    "currency": "USD",
                    "email": "customer@example.com",
                    "order_id": "ORD-67890",
                    "delay": "instant"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Event accepted (and either queued or delivered, depending on `delay`).",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/SuccessResponse" }
              }
            }
          },
          "400": {
            "description": "Invalid tracking key.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" },
                "example": { "success": false, "message": "Tracking key not found." }
              }
            }
          },
          "405": {
            "description": "Data collection disabled for this tracking key. Contact support.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" },
                "example": {
                  "success": false,
                  "message": "Tracking Container data collecting is disabled. Contact support."
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "Send a conversion event (GET form)",
        "description": "Identical contract to the POST form, with all fields supplied as query-string parameters. Use this for fire-and-forget integrations (e.g. tracking pixels embedded in transactional emails) where issuing a POST is impossible. POST is canonical and recommended for reliability.",
        "operationId": "collectHookGet",
        "tags": ["Conversions"],
        "parameters": [
          { "$ref": "#/components/parameters/TrackingKey" },
          {
            "in": "query",
            "name": "event",
            "required": true,
            "schema": { "$ref": "#/components/schemas/EventName" }
          },
          {
            "in": "query",
            "name": "value",
            "schema": { "type": "number" }
          },
          {
            "in": "query",
            "name": "currency",
            "schema": { "type": "string", "example": "EUR" }
          },
          {
            "in": "query",
            "name": "email",
            "schema": { "type": "string", "format": "email" }
          },
          {
            "in": "query",
            "name": "order_id",
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "Event accepted.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/SuccessResponse" }
              }
            }
          },
          "400": {
            "description": "Invalid tracking key.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          }
        }
      }
    }
  },
  "security": [{ "TrackingKey": [] }],
  "components": {
    "securitySchemes": {
      "TrackingKey": {
        "type": "apiKey",
        "in": "query",
        "name": "k",
        "description": "Tracking container key. Obtain from the Tracklution dashboard at app.tracklution.com. This is the only credential the webhook accepts; no Bearer / HMAC layer."
      }
    },
    "parameters": {
      "TrackingKey": {
        "in": "query",
        "name": "k",
        "required": true,
        "description": "Tracking container key. Obtain from the Tracklution dashboard at app.tracklution.com.",
        "schema": {
          "type": "string",
          "minLength": 8,
          "example": "tlk_abc123def456"
        }
      }
    },
    "schemas": {
      "EventName": {
        "type": "string",
        "description": "Standard event name. Custom event names are also accepted and forwarded to platforms that support custom events.",
        "examples": [
          "PageView",
          "ViewContent",
          "AddToCart",
          "InitiateCheckout",
          "AddPaymentInfo",
          "Purchase",
          "Lead",
          "CompleteRegistration",
          "Search",
          "Subscribe",
          "Contact",
          "AddToWishlist",
          "StartTrial",
          "SubmitApplication",
          "FindLocation",
          "Schedule",
          "Donate",
          "CustomizeProduct"
        ]
      },
      "CartContent": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "description": "Product SKU or identifier." },
          "quantity": { "type": "integer", "minimum": 1 },
          "item_price": { "type": "number", "description": "Per-unit price in `currency`." }
        },
        "required": ["id"]
      },
      "ConversionEvent": {
        "type": "object",
        "required": ["event"],
        "additionalProperties": true,
        "description": "A single conversion event. Standard fields are documented below; arbitrary custom properties are allowed and forwarded to connectors that accept them (Meta CAPI custom events, Google Ads custom conversions, custom webhook destinations). Server/webhook flows may also send tracking-cookie values as top-level cookie-mirror fields (`_fbp`, `_gcl_aw`, `_gcl_gs`, `_ga`, `_ga_<MEASUREMENT_ID>`, `__kla_id`, `_rdt_uuid`, `trl_ets`, `vc_inc_s`, `vc`); these are fed into the same cookie pipeline a browser pixel hit uses, recovering attribution that would otherwise be lost on server-only conversions.",
        "properties": {
          "event": { "$ref": "#/components/schemas/EventName" },
          "value": {
            "type": "number",
            "description": "Conversion value in `currency`."
          },
          "currency": {
            "type": "string",
            "description": "ISO 4217 currency code. Required if `value` is set.",
            "example": "EUR"
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Used for cross-device matching. Hashed (SHA-256) before delivery to ad platforms."
          },
          "phoneNumber": {
            "type": "string",
            "description": "E.164-formatted phone (e.g. `+358501234567`). Hashed before delivery."
          },
          "firstName": {
            "type": "string",
            "description": "Customer first name. Hashed before delivery."
          },
          "lastName": {
            "type": "string",
            "description": "Customer last name. Hashed before delivery."
          },
          "birthday": {
            "type": "string",
            "format": "date",
            "description": "ISO date (YYYY-MM-DD). Hashed before delivery."
          },
          "gender": {
            "type": "string",
            "enum": ["male", "female", "other"]
          },
          "address": { "type": "string", "description": "Street address. Hashed before delivery." },
          "postCode": {
            "type": "string",
            "description": "ZIP / postal code. Hashed before delivery."
          },
          "city": { "type": "string", "description": "City. Hashed before delivery." },
          "country": {
            "type": "string",
            "description": "ISO 3166-1 alpha-2 country code (e.g. `FI`, `US`)."
          },
          "order_id": {
            "type": "string",
            "description": "Order identifier. Used as the deduplication key against the client-side pixel."
          },
          "form_id": {
            "type": "string",
            "description": "Form identifier (for Lead events). Free-form."
          },
          "content_ids": {
            "type": "array",
            "items": { "type": "string" },
            "description": "Product SKUs or identifiers."
          },
          "contents": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/CartContent" },
            "description": "Cart or order line items."
          },
          "search_string": {
            "type": "string",
            "description": "Used with the Search event."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Page URL associated with the event. Defaults to the request referer."
          },
          "source": {
            "type": "string",
            "description": "Free-form label visible in the dashboard event log (e.g. `stripe-webhook`, `hubspot-form`)."
          },
          "delay": {
            "type": "string",
            "enum": ["instant"],
            "description": "If `instant`, bypass the batch queue and deliver immediately. Available on Plus plans and above."
          },
          "_fbp": {
            "type": "string",
            "description": "Cookie-mirror field. Meta `_fbp` browser cookie value; replayed into the cookie pipeline as Meta CAPI `user_data.fbp` and attribution `source_secondary_id`."
          },
          "_gcl_aw": {
            "type": "string",
            "description": "Cookie-mirror field. Google Ads `_gcl_aw` cookie; used to recover the `gclid` when no URL `gclid` is present."
          },
          "_gcl_gs": {
            "type": "string",
            "description": "Cookie-mirror field. Google Ads `_gcl_gs` cross-domain handoff cookie. Stored for forward compatibility; not yet consumed."
          },
          "_ga": {
            "type": "string",
            "description": "Cookie-mirror field. GA4 `_ga` cookie (client id). Combined with `_ga_<MEASUREMENT_ID>` to derive the GA4 `ga4clid`."
          },
          "__kla_id": {
            "type": "string",
            "description": "Cookie-mirror field. Klaviyo `__kla_id` cookie; used as the Klaviyo `source_secondary_id`."
          },
          "_rdt_uuid": {
            "type": "string",
            "description": "Cookie-mirror field. Reddit `_rdt_uuid` cookie; used as the Reddit `source_secondary_id` / CAPI `user_data.uuid`."
          },
          "trl_ets": {
            "type": "string",
            "description": "Cookie-mirror field. Tracklution custom-connector attribution fallback cookie."
          },
          "vc_inc_s": {
            "type": "string",
            "description": "Cookie-mirror field. Legacy Tracklution custom-connector cookie (deprecated, still read)."
          },
          "vc": {
            "type": "string",
            "description": "Cookie-mirror field. Tracklution visitor cookie; honored only when its value is prefixed with the tracking key."
          }
        }
      },
      "SuccessResponse": {
        "type": "object",
        "required": ["success", "trace_id"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "trace_id": {
            "type": "string",
            "description": "Opaque base-36 trace identifier (prefixed with `evt_`). Quote when contacting support about a specific event.",
            "example": "evt_8m3k7"
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "required": ["success", "message"],
        "properties": {
          "success": { "type": "boolean", "const": false },
          "message": { "type": "string" }
        }
      }
    }
  },
  "externalDocs": {
    "description": "Tracklution developer documentation",
    "url": "https://www.tracklution.com/docs/"
  }
}
