{
  "openapi": "3.1.0",
  "info": {
    "title": "Cometly Public API v1",
    "description": "Public API for creating, retrieving, and deleting conversion events.",
    "version": "1.3.0"
  },
  "servers": [
    {
      "url": "https://app.cometly.com"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/public-api/v1/events": {
      "get": {
        "summary": "List Events",
        "description": "Retrieve a paginated list of events with optional attribution filtering.",
        "operationId": "listEvents",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "start_date",
            "in": "query",
            "description": "Start date for the query range in YYYY-MM-DD HH:MM:SS format. Interpreted in your space's timezone.",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$",
              "example": "2024-01-01 00:00:00"
            }
          },
          {
            "name": "end_date",
            "in": "query",
            "description": "End date for the query range in YYYY-MM-DD HH:MM:SS format. Must be after start_date and is interpreted in your space's timezone.",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$",
              "example": "2024-01-31 23:59:59"
            }
          },
          {
            "name": "query_mode",
            "in": "query",
            "description": "Determines whether to report metrics by contact or company level.",
            "schema": {
              "type": "string",
              "enum": [
                "profile",
                "company"
              ],
              "default": "profile"
            }
          },
          {
            "name": "event_names",
            "in": "query",
            "description": "Filter results to specific event names. Values: add_payment_info, add_to_cart, complete_registration, contact, initiate_checkout, lead_generated, purchase, schedule, sign_up, start_trial, submit_application, subscribe, upsell_purchase, view_content, webinar_registration. Custom events: custom_event_1 through custom_event_50.",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              },
              "minItems": 1,
              "maxItems": 10,
              "uniqueItems": true
            },
            "style": "form",
            "explode": true
          },
          {
            "name": "sources",
            "in": "query",
            "description": "Filter events by traffic sources. When provided, attribution_model and attribution_window are required.",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              },
              "minItems": 1,
              "maxItems": 15,
              "uniqueItems": true
            },
            "style": "form",
            "explode": true
          },
          {
            "name": "attribution_model",
            "in": "query",
            "description": "Attribution model to use for filtering events. Required when sources are provided.",
            "schema": {
              "type": "string",
              "enum": [
                "first_touch",
                "last_touch",
                "linear",
                "first_platform_touch",
                "last_platform_touch",
                "linear_paid",
                "u_shaped",
                "last_non_direct_touch"
              ]
            }
          },
          {
            "name": "attribution_window",
            "in": "query",
            "description": "Attribution lookback window in days. Required when sources are provided.",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1,
                7,
                14,
                30,
                60,
                90
              ]
            }
          },
          {
            "name": "fields",
            "in": "query",
            "description": "Specify which fields to include in the response. Note: id and event_time_utc are always included for cursor pagination. When sources are provided, touchpoint_id is also automatically included.",
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "id",
                  "profile_id",
                  "company_id",
                  "space_id",
                  "event_name",
                  "configured_name",
                  "amount",
                  "is_upsell",
                  "event_time_utc",
                  "ad_id",
                  "ad_name",
                  "adset_id",
                  "adset_name",
                  "campaign_id",
                  "campaign_name",
                  "account_id",
                  "account_name",
                  "order_id",
                  "order_name",
                  "event_url"
                ]
              },
              "minItems": 1,
              "maxItems": 20,
              "uniqueItems": true,
              "default": [
                "id",
                "event_time_utc"
              ]
            },
            "style": "form",
            "explode": true
          },
          {
            "name": "per_page",
            "in": "query",
            "description": "Number of events to return per page.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Pagination cursor from a previous response.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "custom_field_filters",
            "in": "query",
            "description": "Filter events by the owning contact's custom profile field values. Array of AND-joined conditions, each `{ field, operator, value }` (or `{ field, operator, start, end }` for the `between` operator). The `field` must reference a custom field slot that has been configured with a label in your space (e.g. `profile_field_5`). See the CustomFieldFilterCondition schema for operator vocabulary. Maximum 10 conditions per request.",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/components/schemas/CustomFieldFilterCondition"
              },
              "maxItems": 10
            },
            "style": "deepObject",
            "explode": true
          }
        ],
        "responses": {
          "200": {
            "description": "Events successfully retrieved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "API key doesn't have permission or subscription is inactive.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid parameters provided.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/public-api/v1/events/track": {
      "post": {
        "summary": "Create Event",
        "description": "Create a new event to track conversions and user interactions.",
        "operationId": "createEvent",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NewEvent"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Event accepted and queued for processing.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "integer",
                      "example": 202
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "message"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "API key doesn't have permission or subscription is inactive.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed or missing required parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/public-api/v1/events/{event_id}": {
      "get": {
        "summary": "Get Event",
        "description": "Retrieve details of a specific event by its ID.",
        "operationId": "getEvent",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "event_id",
            "in": "path",
            "description": "The unique identifier of the event to retrieve.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Event successfully retrieved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Event"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "API key doesn't have permission or subscription is inactive.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Event not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid event ID provided.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete Event",
        "description": "Delete a specific event by its ID. This endpoint implements idempotent delete behavior - attempting to delete an event that doesn't exist will still return a success response.",
        "operationId": "deleteEvent",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "event_id",
            "in": "path",
            "description": "The unique identifier of the event to delete.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Event successfully deleted (or already doesn't exist due to idempotent behavior).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "integer",
                      "example": 200
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "message"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "API key doesn't have permission or subscription is inactive.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid event ID provided.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/public-api/v1/companies": {
      "get": {
        "summary": "List Companies",
        "description": "Retrieve a paginated list of companies with optional date filtering.",
        "operationId": "listCompanies",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "per_page",
            "in": "query",
            "description": "Number of companies to return per page. Minimum: 1, Maximum: 1000",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Pagination cursor from a previous response.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_date",
            "in": "query",
            "description": "Filter companies created on or after this date. Format: YYYY-MM-DD HH:MM:SS. Interpreted in your space's timezone.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$",
              "example": "2024-01-01 00:00:00"
            }
          },
          {
            "name": "end_date",
            "in": "query",
            "description": "Filter companies created on or before this date. Format: YYYY-MM-DD HH:MM:SS. Must be after start_date. Interpreted in your space's timezone.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$",
              "example": "2024-01-31 23:59:59"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Companies successfully retrieved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "API key doesn't have permission or subscription is inactive.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid parameters provided.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/public-api/v1/companies/{id}": {
      "get": {
        "summary": "Get Company",
        "description": "Retrieve details of a specific company by its ID.",
        "operationId": "getCompany",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the company to retrieve",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Company successfully retrieved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Company"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "API key doesn't have permission or subscription is inactive.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Company not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid company ID provided.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Update Company",
        "description": "Update an existing company's domain, external ID, or name using sparse PUT semantics. Any field you include replaces the existing value; any field you omit is left untouched. At least one of domain, external_id or name must be provided.",
        "operationId": "updateCompany",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the company to update",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "domain": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 255,
                    "description": "New domain for the company. This is an identifier, not just a label: it decides which company future events from that email domain are matched to. Trimmed and lowercased before storing; a blank string is treated as `null`. Omit the key to leave the existing domain untouched. Send `null` (or blank) to release the company's domain claim \u2014 the company keeps its `id`, history, and contacts, but future events from that domain will create or match a different company. If the domain already belongs to another company in the Space, the request is rejected with `409` and nothing is changed."
                  },
                  "external_id": {
                    "type": [
                      "string",
                      "integer",
                      "null"
                    ],
                    "minLength": 1,
                    "maxLength": 190,
                    "description": "New external ID for the company \u2014 your own account/company identifier, the same value sent as `company_external_id` on events. This is an identifier, not just a label: it decides which company future events carrying that `company_external_id` are matched to. Trimmed, but case is preserved (byte-exact) \u2014 unlike domain, it is never lowercased. 1 to 190 characters after trimming; a blank string is treated as `null`. Integers are accepted and stored as their decimal string. Omit the key to leave the existing external ID untouched. Send `null` (or blank) to release the company's external ID claim. If the external ID already belongs to another company in the Space, the request is rejected with `409` and nothing is changed. Only honored by event ingestion when the Space's company identity mode is External ID; in Auto mode the value is stored and returned but ignored for grouping."
                  },
                  "name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "New name for the company. Omit the key to leave the existing name untouched. Cannot be `null` \u2014 the stored value is a required column, so sending `null` returns a `422`."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Company successfully updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Company"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "API key doesn't have permission or subscription is inactive.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Company not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The given domain or external_id already belongs to another company in the Space. Nothing is changed; re-point contacts or update the other company instead of retrying.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyIdentifierConflict"
                }
              }
            }
          },
          "422": {
            "description": "Invalid parameters provided.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/public-api/v1/contacts": {
      "post": {
        "summary": "Create Contact",
        "description": "Create a new contact with arrays of emails, phones, names, and locations.",
        "operationId": "createContact",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "emails"
                ],
                "properties": {
                  "emails": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "email"
                    },
                    "minItems": 1,
                    "description": "Array of email addresses. At least one is required."
                  },
                  "phones": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Array of phone numbers. Optional."
                  },
                  "names": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Array of names. Optional."
                  },
                  "locations": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Array of locations. Optional."
                  },
                  "custom_fields": {
                    "type": "object",
                    "description": "Object of custom profile field values keyed by field slug (profile_field_1 through profile_field_30). Fields 1-15 accept text, 16-25 accept numbers, 26-30 accept dates. Optional.",
                    "additionalProperties": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Contact successfully created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactDetail"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "API key doesn't have permission or subscription is inactive.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid parameters provided.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "List Contacts",
        "description": "Retrieve a paginated list of contacts with primary data only, filtered by creation date and/or email address.",
        "operationId": "listContacts",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "email",
            "in": "query",
            "description": "Filter contacts by email address. Accepts a single address, a comma-separated list (the serialization this spec generates), or a repeated `email[]` parameter. Maximum 100 addresses per request. Matching is exact and case-insensitive (whitespace trimmed), and matches both the contact's primary address and any of its alternate addresses, including addresses captured on profiles later merged into the contact. When supplied, start_date/end_date become optional; otherwise start_date/end_date remain required as a pair. A contact matched on an alternate address is returned with its primary address in the `email` field, not the address you queried; pass include_all_emails=1 to receive the `emails` array and map batched results back to your input.",
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "format": "email"
              },
              "maxItems": 100
            },
            "style": "form",
            "explode": false
          },
          {
            "name": "start_date",
            "in": "query",
            "description": "Start date and time for filtering contacts by creation date in YYYY-MM-DD HH:MM:SS format. Interpreted in your space's timezone. Required unless email is supplied; when present, end_date must also be present.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$",
              "example": "2024-01-15 00:00:00"
            }
          },
          {
            "name": "end_date",
            "in": "query",
            "description": "End date and time for filtering contacts by creation date in YYYY-MM-DD HH:MM:SS format. Must be after start_date. Interpreted in your space's timezone. Required unless email is supplied; when present, start_date must also be present.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$",
              "example": "2024-01-15 23:59:59"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "description": "Number of contacts to return per page. Minimum: 1, Maximum: 5000",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 5000,
              "default": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Pagination cursor from a previous response.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "include_comet_tokens",
            "in": "query",
            "description": "When set to 1, includes the last 5 comet tokens for each contact, ordered by most recent first. Accepts: 1 or 0.",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ],
              "default": 0
            }
          },
          {
            "name": "include_all_emails",
            "in": "query",
            "description": "When set to 1, includes all email addresses associated with the contact, including emails from merged profiles. Accepts: 1 or 0.",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ],
              "default": 0
            }
          },
          {
            "name": "include_custom_fields",
            "in": "query",
            "description": "When set to 1, includes all 30 custom field columns for each contact. Fields 1-15 are text, 16-25 are numeric, 26-30 are date. Accepts: 1 or 0.",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ],
              "default": 0
            }
          },
          {
            "name": "use_custom_field_labels",
            "in": "query",
            "description": "When set to 1, custom field keys will use user-defined labels instead of raw column names (e.g. 'Customer Age' instead of 'profile_field_1'). Only applies when include_custom_fields=1. Fields without a configured label keep their raw column name. Accepts: 1 or 0.",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ],
              "default": 0
            }
          },
          {
            "name": "custom_field_filters",
            "in": "query",
            "description": "Filter contacts by their custom profile field values. Array of AND-joined conditions, each `{ field, operator, value }` (or `{ field, operator, start, end }` for the `between` operator). The `field` must reference a custom field slot that has been configured with a label in your space (e.g. `profile_field_5`). See the CustomFieldFilterCondition schema for operator vocabulary. Maximum 10 conditions per request.",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/components/schemas/CustomFieldFilterCondition"
              },
              "maxItems": 10
            },
            "style": "deepObject",
            "explode": true
          }
        ],
        "responses": {
          "200": {
            "description": "Contacts successfully retrieved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "API key doesn't have permission or subscription is inactive.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid parameters provided.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/public-api/v1/contacts/{id}": {
      "get": {
        "summary": "Get Contact",
        "description": "Retrieve details of a specific contact by its ID. Automatically resolves merged profiles.",
        "operationId": "getContact",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the contact to retrieve",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "include_comet_tokens",
            "in": "query",
            "description": "When set to 1, includes the last 5 comet tokens associated with this contact, ordered by most recent first. Accepts: 1 or 0.",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ],
              "default": 0
            }
          },
          {
            "name": "include_events",
            "in": "query",
            "description": "When set to 1, includes the contact's full event journey \u2014 all conversions and touchpoints sorted by most recent first. Accepts: 1 or 0.",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ],
              "default": 0
            }
          },
          {
            "name": "hide_direct_touchpoints",
            "in": "query",
            "description": "When set to 1 (default), direct touchpoints are excluded from the events list. Set to 0 to include them. Only applies when include_events=1. Accepts: 1 or 0.",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ],
              "default": 1
            }
          },
          {
            "name": "use_custom_field_labels",
            "in": "query",
            "description": "When set to 1, custom field keys in the custom_fields object will use user-defined labels instead of raw column names (e.g. 'Customer Age' instead of 'profile_field_1'). Fields without a configured label keep their raw column name. Accepts: 1 or 0.",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ],
              "default": 0
            }
          },
          {
            "name": "include_browsing_session_data",
            "in": "query",
            "description": "When set to 1, includes up to the last 1000 raw browsing session hits (page views) for this contact, ordered by most recent first. Accepts: 1 or 0.",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ],
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Contact successfully retrieved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactDetail"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "API key doesn't have permission or subscription is inactive.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Contact not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid contact ID provided.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Update Contact",
        "description": "Update an existing contact's emails, phones, names, locations, or custom fields using sparse PUT semantics. Any field you include is treated as the full, authoritative list for that collection \u2014 existing values are deleted and replaced. Any field you omit is left untouched. Empty arrays wipe a collection. Providing custom_fields clears every key not in the object. At least one of emails, phones, names, locations, or custom_fields must be provided.",
        "operationId": "updateContact",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the contact to update. Merged profile aliases are automatically resolved.",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "emails": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "email"
                    },
                    "description": "Full replacement list of email addresses. Provide [] to wipe all emails."
                  },
                  "phones": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Full replacement list of phone numbers. Provide [] to wipe all phones."
                  },
                  "names": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Full replacement list of names. Provide [] to wipe all names."
                  },
                  "locations": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Full replacement list of locations. Provide [] to wipe all locations."
                  },
                  "custom_fields": {
                    "type": "object",
                    "description": "Full replacement of custom profile fields keyed by profile_field_1 through profile_field_30. Every key NOT included is set to null. Provide {} to wipe all 30 fields. Fields 1-15 accept text, 16-25 accept numbers (string or number), 26-30 accept dates.",
                    "additionalProperties": {
                      "type": [
                        "string",
                        "number",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Contact successfully updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactUpdateResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "API key doesn't have permission or subscription is inactive.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Contact not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid parameters provided.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/public-api/v1/contacts/{id}/company": {
      "put": {
        "summary": "Attach Contact Company",
        "description": "Attach a contact to a company. A contact belongs to at most one company per Space, so this moves it off any company it currently belongs to. The contact's conversions, touchpoints, and visit metadata are re-stamped with the new company id in the same transaction. Idempotent: repeating with the current company id re-stamps the rows again, repairing any that drifted.",
        "operationId": "attachContactCompany",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the contact to attach. Merged profile aliases are automatically resolved.",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "company_id": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "The unique identifier of the company to attach the contact to. Must belong to a company in the same Space as the contact."
                  }
                },
                "required": [
                  "company_id"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Contact successfully attached to the company.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactCompanyResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "API key doesn't have permission or subscription is inactive.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Contact not found, or company_id does not match a company in this Space.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid parameters provided.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Detach Contact Company",
        "description": "Detach a contact from its company, leaving it with no company. The contact's conversions, touchpoints, and visit metadata are re-stamped with a null company id in the same transaction. No request body. Idempotent: returns 200 when the contact already had no company.",
        "operationId": "detachContactCompany",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the contact to detach. Merged profile aliases are automatically resolved.",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Contact successfully detached from its company. Also returned as a no-op when the contact already had no company.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactCompanyResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "API key doesn't have permission or subscription is inactive.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Contact not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid contact ID provided.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/public-api/v1/contacts/by-email/{email}": {
      "get": {
        "summary": "Get Contact by Email",
        "description": "Retrieve a single contact by its email address, addressed as a path segment. Resolution matches the email filter on List Contacts: exact, case-insensitive, whitespace-trimmed, and spanning the contact's primary email, secondary emails, and emails captured on profiles later merged into the contact. Returns 404 if no contact matches and 409 if more than one contact matches. The response body is identical to GET /contacts/{id}.",
        "operationId": "getContactByEmailPath",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "email",
            "in": "path",
            "description": "The email address of the contact to retrieve. Accepts a raw @ or a percent-encoded %40. Matches both the contact's primary address and any of its alternate addresses, including addresses captured on profiles later merged into the contact. Matching is exact (not partial or fuzzy) and case-insensitive; surrounding whitespace is trimmed. Returns 409 when more than one contact matches.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "email"
            }
          },
          {
            "name": "include_comet_tokens",
            "in": "query",
            "description": "When set to 1, includes the last 5 comet tokens associated with this contact, ordered by most recent first. Accepts: 1 or 0.",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ],
              "default": 0
            }
          },
          {
            "name": "include_events",
            "in": "query",
            "description": "When set to 1, includes the contact's full event journey \u2014 all conversions and touchpoints sorted by most recent first. Accepts: 1 or 0.",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ],
              "default": 0
            }
          },
          {
            "name": "hide_direct_touchpoints",
            "in": "query",
            "description": "When set to 1 (default), direct touchpoints are excluded from the events list. Set to 0 to include them. Only applies when include_events=1. Accepts: 1 or 0.",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ],
              "default": 1
            }
          },
          {
            "name": "use_custom_field_labels",
            "in": "query",
            "description": "When set to 1, custom field keys in the custom_fields object will use user-defined labels instead of raw column names (e.g. 'Customer Age' instead of 'profile_field_1'). Fields without a configured label keep their raw column name. Accepts: 1 or 0.",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ],
              "default": 0
            }
          },
          {
            "name": "include_browsing_session_data",
            "in": "query",
            "description": "When set to 1, includes up to the last 1000 raw browsing session hits (page views) for this contact, ordered by most recent first. Accepts: 1 or 0.",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ],
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Exactly one contact matched and was retrieved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactDetail"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "API key doesn't have permission or subscription is inactive.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No contact matches the given email.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "More than one contact matches this email. Nothing is guessed; fetch the matches via GET /contacts?email= or request one of the returned contact_ids directly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactPiiDeleteConflict"
                }
              }
            }
          },
          "422": {
            "description": "Invalid email provided.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/public-api/v1/contacts/by-email": {
      "get": {
        "summary": "Get Contact by Email (Query String)",
        "description": "Retrieve a single contact by its email address, addressed as a query parameter. Behaves identically to GET /public-api/v1/contacts/by-email/{email}, including resolution rules and status codes.",
        "operationId": "getContactByEmail",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "email",
            "in": "query",
            "description": "The email address of the contact to retrieve. Matches both the contact's primary address and any of its alternate addresses, including addresses captured on profiles later merged into the contact. Matching is exact (not partial or fuzzy) and case-insensitive; surrounding whitespace is trimmed. Returns 409 when more than one contact matches.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "email"
            }
          },
          {
            "name": "include_comet_tokens",
            "in": "query",
            "description": "When set to 1, includes the last 5 comet tokens associated with this contact, ordered by most recent first. Accepts: 1 or 0.",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ],
              "default": 0
            }
          },
          {
            "name": "include_events",
            "in": "query",
            "description": "When set to 1, includes the contact's full event journey \u2014 all conversions and touchpoints sorted by most recent first. Accepts: 1 or 0.",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ],
              "default": 0
            }
          },
          {
            "name": "hide_direct_touchpoints",
            "in": "query",
            "description": "When set to 1 (default), direct touchpoints are excluded from the events list. Set to 0 to include them. Only applies when include_events=1. Accepts: 1 or 0.",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ],
              "default": 1
            }
          },
          {
            "name": "use_custom_field_labels",
            "in": "query",
            "description": "When set to 1, custom field keys in the custom_fields object will use user-defined labels instead of raw column names (e.g. 'Customer Age' instead of 'profile_field_1'). Fields without a configured label keep their raw column name. Accepts: 1 or 0.",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ],
              "default": 0
            }
          },
          {
            "name": "include_browsing_session_data",
            "in": "query",
            "description": "When set to 1, includes up to the last 1000 raw browsing session hits (page views) for this contact, ordered by most recent first. Accepts: 1 or 0.",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ],
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Exactly one contact matched and was retrieved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactDetail"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "API key doesn't have permission or subscription is inactive.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No contact matches the given email.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "More than one contact matches this email. Nothing is guessed; fetch the matches via GET /contacts?email= or request one of the returned contact_ids directly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactPiiDeleteConflict"
                }
              }
            }
          },
          "422": {
            "description": "Invalid email provided.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/public-api/v1/contacts/{id}/pii": {
      "delete": {
        "summary": "Delete Contact PII",
        "description": "Permanently scrub a contact's personally identifiable information by contact ID. Preserves the contact record, its events, and merge history. Resolution and validation happen synchronously; the scrub itself is queued and this endpoint returns 202 Accepted immediately.",
        "operationId": "deleteContactPii",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the contact whose PII should be deleted. Merged profile aliases are automatically resolved to the current canonical contact.",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "202": {
            "description": "PII deletion successfully queued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactPiiDeleteResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "API key doesn't have permission or subscription is inactive.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Contact not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid contact ID provided, or both id and email were supplied.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/public-api/v1/contacts/pii": {
      "delete": {
        "summary": "Delete Contact PII by Email",
        "description": "Permanently scrub a contact's personally identifiable information by email address. Preserves the contact record, its events, and merge history. Resolution and validation happen synchronously; the scrub itself is queued and this endpoint returns 202 Accepted immediately. Rejects with 409 if the email matches more than one distinct contact.",
        "operationId": "deleteContactPiiByEmail",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "email",
            "in": "query",
            "description": "The email address of the contact whose PII should be deleted. Matches against both the contact's full email history (including emails inherited from merged profiles) and its current primary email.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "email"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "PII deletion successfully queued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactPiiDeleteResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "API key doesn't have permission or subscription is inactive.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No contact matches the given email.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Multiple contacts match this email. Nothing is deleted; retry once per contact id instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactPiiDeleteConflict"
                }
              }
            }
          },
          "422": {
            "description": "Invalid email provided, or both id and email were supplied.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "CustomFieldFilterCondition": {
        "type": "object",
        "description": "A single AND-joined filter condition targeting a custom profile field column. Used in the `custom_field_filters` array on List Contacts and List Events. The `field` must reference a slot configured for your space (slots 1-15 are text, 16-25 are numeric, 26-30 are date). Operator vocabulary depends on field type \u2014 see the `operator` enum below.",
        "required": [
          "field",
          "operator"
        ],
        "properties": {
          "field": {
            "type": "string",
            "pattern": "^profile_field_(?:[1-9]|[12][0-9]|30)$",
            "description": "Custom field column slug. Must be one of `profile_field_1` through `profile_field_30` AND configured with a label in your space.",
            "example": "profile_field_5"
          },
          "operator": {
            "type": "string",
            "description": "Comparison operator. Valid operators by field type \u2014 text (1-15): equal_to, not_equal_to, contains, not_contains, starts_with, ends_with, contains_word, any, unknown. Number (16-25): equal_to, not_equal_to, greater_than, greater_than_or_equal_to, less_than, less_than_or_equal_to, any, unknown. Date (26-30): equal_to, between, greater_than, less_than, age_greater_than, age_equal_to, age_less_than, any, unknown. `any` matches contacts where the field has a value; `unknown` matches contacts where the field is empty or unset. For numeric fields, `any` requires a value greater than 0 and `unknown` matches 0 or unset. `not_equal_to` and `not_contains` do not include contacts where the field is unset. Date comparisons (equal_to, greater_than, less_than, between) use your space's configured timezone; equal_to matches the full calendar day.",
            "enum": [
              "equal_to",
              "not_equal_to",
              "between",
              "greater_than",
              "greater_than_or_equal_to",
              "less_than",
              "less_than_or_equal_to",
              "age_greater_than",
              "age_equal_to",
              "age_less_than",
              "starts_with",
              "ends_with",
              "contains",
              "not_contains",
              "contains_word",
              "any",
              "unknown"
            ]
          },
          "value": {
            "description": "The comparison value. Required for all operators except `any`, `unknown`, and `between`. Type matches the field type \u2014 string for text fields, number for numeric fields, YYYY-MM-DD (or YYYY-MM-DD HH:MM:SS) for date fields. For age operators (age_greater_than, age_equal_to, age_less_than) on date fields, pass a whole-number day count (e.g. 30 for 30 days ago).",
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              }
            ],
            "nullable": true
          },
          "start": {
            "description": "Range start. Required only for the `between` operator; type matches the field type.",
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              }
            ],
            "nullable": true
          },
          "end": {
            "description": "Range end. Required only for the `between` operator; type matches the field type.",
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "number"
              }
            ],
            "nullable": true
          }
        }
      },
      "Event": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The unique identifier of the event."
          },
          "profile_id": {
            "type": "string",
            "description": "The identifier of the contact profile associated with this event."
          },
          "company_id": {
            "type": "string",
            "description": "Your company identifier."
          },
          "space_id": {
            "type": "string",
            "description": "The space identifier this event belongs to."
          },
          "event_name": {
            "type": "string",
            "description": "The name of the event (e.g., purchase, custom_event_1)."
          },
          "configured_name": {
            "type": "string",
            "description": "The configured name of the event. For custom events (custom_event_1 through custom_event_50), this is the user-configured name. For standard events, this equals event_name."
          },
          "amount": {
            "type": "number",
            "description": "Transaction amount."
          },
          "is_upsell": {
            "type": "boolean",
            "description": "Indicates if this is an upsell transaction."
          },
          "event_time_utc": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp of when the event occurred (UTC)."
          },
          "order_id": {
            "type": "string",
            "description": "Order identifier."
          },
          "order_name": {
            "type": "string",
            "description": "Order name or description."
          },
          "event_url": {
            "type": "string",
            "description": "The full URL where the event occurred."
          }
        }
      },
      "EventListItem": {
        "type": "object",
        "description": "Event fields returned by the list endpoint. Fields are included based on the fields query parameter.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Event identifier."
          },
          "profile_id": {
            "type": "string",
            "description": "Contact profile identifier."
          },
          "company_id": {
            "type": "string",
            "description": "Company identifier."
          },
          "space_id": {
            "type": "string",
            "description": "Space identifier."
          },
          "event_name": {
            "type": "string",
            "description": "Event name."
          },
          "configured_name": {
            "type": "string",
            "description": "The configured name of the event. For custom events (custom_event_1 through custom_event_50), this is the user-configured name. For standard events, this equals event_name."
          },
          "amount": {
            "type": "number",
            "description": "Transaction amount."
          },
          "is_upsell": {
            "type": "boolean",
            "description": "Upsell flag."
          },
          "event_time_utc": {
            "type": "string",
            "format": "date-time",
            "description": "Event timestamp in UTC."
          },
          "ad_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Platform-specific ad identifier. Requires sources to be provided."
          },
          "ad_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Ad name from the ad platform. Requires sources to be provided."
          },
          "adset_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Platform-specific ad set identifier. Requires sources to be provided."
          },
          "adset_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Ad set name from the ad platform. Requires sources to be provided."
          },
          "campaign_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Platform-specific campaign identifier. Requires sources to be provided."
          },
          "campaign_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Campaign name from the ad platform. Requires sources to be provided."
          },
          "account_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Platform-specific ad account identifier. Requires sources to be provided."
          },
          "account_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Ad account name from the ad platform. Requires sources to be provided."
          },
          "touchpoint_id": {
            "type": "string",
            "description": "Touchpoint identifier."
          },
          "order_id": {
            "type": "string",
            "description": "Order identifier."
          },
          "order_name": {
            "type": "string",
            "description": "Order name or description."
          },
          "event_url": {
            "type": "string",
            "description": "The full URL where the event occurred."
          }
        }
      },
      "EventListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EventListItem"
            }
          },
          "path": {
            "type": "string",
            "description": "The base URL path for the endpoint."
          },
          "per_page": {
            "type": "integer",
            "description": "Number of items per page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Cursor for the next page of results."
          },
          "next_page_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Full URL for the next page of results."
          },
          "prev_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Cursor for the previous page of results."
          },
          "prev_page_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Full URL for the previous page of results."
          }
        },
        "required": [
          "data",
          "path",
          "per_page",
          "next_cursor",
          "next_page_url",
          "prev_cursor",
          "prev_page_url"
        ]
      },
      "NewEvent": {
        "type": "object",
        "description": "Payload for creating an event. At least one identification method is required: email, comet_token, or fingerprint+ip.",
        "properties": {
          "event_name": {
            "type": "string",
            "description": "Event name. Standard events: lead_generated, view_content, schedule, purchase, subscribe, add_to_cart, contact, initiate_checkout, add_payment_info, complete_registration, start_trial, sign_up, submit_application, webinar_registration. Custom events: custom_event_1 through custom_event_50."
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "User's email address."
          },
          "comet_token": {
            "type": "string",
            "description": "Cometly tracking token."
          },
          "fingerprint": {
            "type": "string",
            "description": "Browser fingerprint for user identification."
          },
          "ip": {
            "type": "string",
            "description": "User's IP address."
          },
          "tracking_id": {
            "type": "string",
            "description": "Custom tracking identifier."
          },
          "company_external_id": {
            "type": ["string", "integer", "null"],
            "maxLength": 190,
            "description": "Groups this contact into a company using your own account or company identifier. Trimmed; 1–190 characters after trimming; case-preserved and stored byte-exact (never lowercased). A blank string is treated as absent (null); floats, arrays, and booleans return 422. Unrelated to tracking_id: tracking_id merges events into a single contact and never groups companies, while company_external_id groups contacts into a company and never merges contacts or takes part in contact matching. Only honored when the Space's company identity mode is set to External ID in Space Settings; in the default Auto mode (companies grouped by business-email domain) the value is accepted and stored but ignored for grouping."
          },
          "company_name": {
            "type": ["string", "integer", "null"],
            "maxLength": 255,
            "description": "Display name for the company identified by company_external_id. Trimmed; 1–255 characters after trimming. A blank string is treated as absent (null); floats, arrays, and booleans return 422. Last write wins and the value is never used for matching — two companies with the same name stay separate. Ignored when company_external_id is not also provided."
          },
          "full_name": {
            "type": "string",
            "description": "User's full name."
          },
          "first_name": {
            "type": "string",
            "description": "User's first name."
          },
          "last_name": {
            "type": "string",
            "description": "User's last name."
          },
          "phone": {
            "type": "string",
            "description": "User's phone number."
          },
          "user_agent": {
            "type": "string",
            "description": "Browser user agent string."
          },
          "event_time": {
            "description": "Timestamp of when the event occurred. Accepts ISO 8601 format or Unix timestamp in seconds.",
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "integer"
              }
            ]
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "The URL where the event occurred."
          },
          "amount": {
            "type": "number",
            "description": "Transaction amount (for purchase events)."
          },
          "order_id": {
            "type": "string",
            "description": "Unique order identifier. Used for deduplication \u2014 multiple events with the same order_id may be treated as duplicates."
          },
          "order_name": {
            "type": "string",
            "description": "Order name or description."
          },
          "checkout_token": {
            "type": "string",
            "description": "Checkout session token."
          },
          "is_upsell": {
            "type": "boolean",
            "description": "Indicates if this is an upsell transaction."
          },
          "upsell_common_id": {
            "type": "string",
            "description": "Common identifier linking upsells to original orders."
          },
          "comet_source": {
            "type": "string",
            "description": "Traffic source (e.g., \"google\", \"facebook\")."
          },
          "comet_network": {
            "type": "string",
            "description": "Ad network name."
          },
          "comet_campaign": {
            "type": "string",
            "description": "Campaign name or identifier."
          },
          "comet_ad_group": {
            "type": "string",
            "description": "Ad group name or identifier."
          },
          "comet_ad_id": {
            "type": "string",
            "description": "Specific ad identifier."
          },
          "comet_keyword": {
            "type": "string",
            "description": "Keyword that triggered the ad."
          },
          "comet_type": {
            "type": "string",
            "description": "Traffic type (e.g., \"cpc\", \"organic\")."
          },
          "idempotency_key": {
            "type": "string",
            "description": "Unique key to prevent duplicate event processing."
          },
          "do_not_capi": {
            "type": "boolean",
            "description": "Set to true to prevent this event from being sent to Conversions API integrations."
          },
          "profile_field_1": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom profile field 1 (text). Fields 1-15 accept text, 16-25 accept numbers (string or number), 26-30 accept dates.",
            "maxLength": 10240
          },
          "profile_field_16": {
            "type": [
              "string",
              "number",
              "null"
            ],
            "description": "Custom profile field 16 (numeric). Accepts a number or numeric string."
          }
        },
        "additionalProperties": {
          "description": "Custom profile fields profile_field_1 through profile_field_30. Fields 1-15 accept text, 16-25 accept numbers (string or number), 26-30 accept dates.",
          "type": [
            "string",
            "number",
            "null"
          ]
        },
        "required": [
          "event_name"
        ],
        "anyOf": [
          {
            "required": [
              "email"
            ]
          },
          {
            "required": [
              "comet_token"
            ]
          },
          {
            "required": [
              "fingerprint",
              "ip"
            ]
          }
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "description": "Error description explaining what went wrong."
          }
        },
        "required": [
          "message"
        ]
      },
      "Company": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The unique identifier of the company."
          },
          "domain": {
            "type": [
              "string",
              "null"
            ],
            "description": "The domain associated with this company. `null` if the company was created from a customer-supplied external ID with no associated email domain, or if its domain claim was released via Update Company."
          },
          "external_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The customer-supplied external ID associated with this company (your own account/company identifier). `null` if the company was created from an email domain alone, or if its external ID claim was released via Update Company."
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "description": "The name associated with this company."
          }
        },
        "required": [
          "id"
        ]
      },
      "CompanyListItem": {
        "type": "object",
        "description": "Company list item. Unlike the Company schema returned by Get Company and Update Company, `name` is not included in the list view.",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The unique identifier of the company."
          },
          "domain": {
            "type": [
              "string",
              "null"
            ],
            "description": "The domain associated with this company. `null` if the company was created from a customer-supplied external ID with no associated email domain, or if its domain claim was released via Update Company."
          },
          "external_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The customer-supplied external ID associated with this company (your own account/company identifier). `null` if the company was created from an email domain alone, or if its external ID claim was released via Update Company."
          }
        },
        "required": [
          "id"
        ]
      },
      "CompanyListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CompanyListItem"
            }
          },
          "path": {
            "type": "string",
            "description": "The base URL path for the endpoint."
          },
          "per_page": {
            "type": "integer",
            "description": "Number of items per page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Cursor for the next page of results."
          },
          "next_page_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Full URL for the next page of results."
          },
          "prev_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Cursor for the previous page of results."
          },
          "prev_page_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Full URL for the previous page of results."
          }
        },
        "required": [
          "data",
          "path",
          "per_page",
          "next_cursor",
          "next_page_url",
          "prev_cursor",
          "prev_page_url"
        ]
      },
      "CompanyIdentifierConflict": {
        "type": "object",
        "description": "409 response from the Update Company endpoint when the given domain or external_id already belongs to another company in the Space. Nothing is changed.",
        "properties": {
          "message": {
            "type": "string",
            "description": "Error description naming the conflicting identifier."
          },
          "field": {
            "type": "string",
            "enum": [
              "domain",
              "external_id"
            ],
            "description": "The identifier field that caused the conflict."
          },
          "conflicting_company_id": {
            "type": "integer",
            "description": "The ID of the company that already owns this domain in the Space."
          }
        },
        "required": [
          "message",
          "field",
          "conflicting_company_id"
        ]
      },
      "Contact": {
        "type": "object",
        "description": "Contact list item with primary data only",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The unique identifier of the contact."
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "description": "Primary email address."
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Primary name."
          },
          "phone": {
            "type": [
              "string",
              "null"
            ],
            "description": "Primary phone number."
          },
          "location": {
            "type": [
              "string",
              "null"
            ],
            "description": "Primary location."
          },
          "comet_tokens": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Array of comet tokens associated with this contact. Maximum 5 most recent. Ordered by most recent first. Only included when include_comet_tokens=true is specified."
          },
          "emails": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Array of all email addresses associated with this contact, including emails from merged profiles. Only included when include_all_emails=1 is specified."
          },
          "profile_field_1": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom field 1 value. Only included when include_custom_fields=1."
          },
          "profile_field_2": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom field 2 value. Only included when include_custom_fields=1."
          },
          "profile_field_3": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom field 3 value. Only included when include_custom_fields=1."
          },
          "profile_field_4": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom field 4 value. Only included when include_custom_fields=1."
          },
          "profile_field_5": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom field 5 value. Only included when include_custom_fields=1."
          },
          "profile_field_6": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom field 6 value. Only included when include_custom_fields=1."
          },
          "profile_field_7": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom field 7 value. Only included when include_custom_fields=1."
          },
          "profile_field_8": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom field 8 value. Only included when include_custom_fields=1."
          },
          "profile_field_9": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom field 9 value. Only included when include_custom_fields=1."
          },
          "profile_field_10": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom field 10 value. Only included when include_custom_fields=1."
          },
          "profile_field_11": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom field 11 value. Only included when include_custom_fields=1."
          },
          "profile_field_12": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom field 12 value. Only included when include_custom_fields=1."
          },
          "profile_field_13": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom field 13 value. Only included when include_custom_fields=1."
          },
          "profile_field_14": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom field 14 value. Only included when include_custom_fields=1."
          },
          "profile_field_15": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom field 15 value. Only included when include_custom_fields=1."
          },
          "profile_field_16": {
            "type": [
              "number",
              "null"
            ],
            "description": "Custom field 16 value (number type). Only included when include_custom_fields=1."
          },
          "profile_field_17": {
            "type": [
              "number",
              "null"
            ],
            "description": "Custom field 17 value (number type). Only included when include_custom_fields=1."
          },
          "profile_field_18": {
            "type": [
              "number",
              "null"
            ],
            "description": "Custom field 18 value (number type). Only included when include_custom_fields=1."
          },
          "profile_field_19": {
            "type": [
              "number",
              "null"
            ],
            "description": "Custom field 19 value (number type). Only included when include_custom_fields=1."
          },
          "profile_field_20": {
            "type": [
              "number",
              "null"
            ],
            "description": "Custom field 20 value (number type). Only included when include_custom_fields=1."
          },
          "profile_field_21": {
            "type": [
              "number",
              "null"
            ],
            "description": "Custom field 21 value (number type). Only included when include_custom_fields=1."
          },
          "profile_field_22": {
            "type": [
              "number",
              "null"
            ],
            "description": "Custom field 22 value (number type). Only included when include_custom_fields=1."
          },
          "profile_field_23": {
            "type": [
              "number",
              "null"
            ],
            "description": "Custom field 23 value (number type). Only included when include_custom_fields=1."
          },
          "profile_field_24": {
            "type": [
              "number",
              "null"
            ],
            "description": "Custom field 24 value (number type). Only included when include_custom_fields=1."
          },
          "profile_field_25": {
            "type": [
              "number",
              "null"
            ],
            "description": "Custom field 25 value (number type). Only included when include_custom_fields=1."
          },
          "profile_field_26": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom field 26 value (date type). Only included when include_custom_fields=1."
          },
          "profile_field_27": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom field 27 value (date type). Only included when include_custom_fields=1."
          },
          "profile_field_28": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom field 28 value (date type). Only included when include_custom_fields=1."
          },
          "profile_field_29": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom field 29 value (date type). Only included when include_custom_fields=1."
          },
          "profile_field_30": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom field 30 value (date type). Only included when include_custom_fields=1."
          }
        },
        "required": [
          "id",
          "email",
          "name",
          "phone",
          "location"
        ]
      },
      "ContactDetail": {
        "type": "object",
        "description": "Detailed contact with all associated data including merged profiles",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The unique identifier of the contact."
          },
          "emails": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Array of email addresses associated with this contact, including from merged profiles. Maximum 25 most recent. Ordered by most recent first."
          },
          "phones": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Array of phone numbers associated with this contact, including from merged profiles. Maximum 25 most recent. Ordered by most recent first."
          },
          "names": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Array of names associated with this contact, including from merged profiles. Maximum 25 most recent. Ordered by most recent first."
          },
          "locations": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Array of locations associated with this contact, including from merged profiles. Maximum 25 most recent. Ordered by most recent first."
          },
          "comet_tokens": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Array of comet tokens associated with this contact. Maximum 5 most recent. Ordered by most recent first. Only included when include_comet_tokens=true is specified."
          },
          "events": {
            "type": "array",
            "description": "Array of the contact's conversions and touchpoints, sorted by most recent first. Only included when include_events=1 is specified.",
            "items": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/ContactConversionEvent"
                },
                {
                  "$ref": "#/components/schemas/ContactTouchpointEvent"
                }
              ]
            }
          },
          "custom_fields": {
            "type": "object",
            "description": "Object containing all 25 custom fields. Each field is a string or null.",
            "properties": {
              "profile_field_1": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "profile_field_2": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "profile_field_3": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "profile_field_4": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "profile_field_5": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "profile_field_6": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "profile_field_7": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "profile_field_8": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "profile_field_9": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "profile_field_10": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "profile_field_11": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "profile_field_12": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "profile_field_13": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "profile_field_14": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "profile_field_15": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "profile_field_16": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "profile_field_17": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "profile_field_18": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "profile_field_19": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "profile_field_20": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "profile_field_21": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "profile_field_22": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "profile_field_23": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "profile_field_24": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "profile_field_25": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "profile_field_26": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "profile_field_27": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "profile_field_28": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "profile_field_29": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "profile_field_30": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "browsing_session_hits": {
            "type": "array",
            "description": "Array of raw browsing session hits (page views) for this contact, ordered by most recent first. Capped at 1000 hits. Only included when include_browsing_session_data=1 is specified.",
            "items": {
              "type": "object",
              "properties": {
                "event_url": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Full URL (host + path + ?query) where the hit occurred. Null when host is unavailable."
                },
                "referrer_host": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "source": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "country": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "device_type": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "browser": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "os": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "event_name": {
                  "type": "string"
                },
                "event_time_utc": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            }
          }
        },
        "required": [
          "id",
          "emails",
          "phones",
          "names",
          "locations"
        ]
      },
      "ContactUpdateResponse": {
        "type": "object",
        "description": "Response from the Update Contact endpoint. Echoes the canonical contact id and only the collections that were included in the PUT request body (sparse-PUT semantics). Omitted request keys are absent here too.",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The canonical contact id (after resolving merged-profile aliases)."
          },
          "emails": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The new emails list, present only when `emails` was provided in the request body."
          },
          "phones": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The new phones list, present only when `phones` was provided in the request body."
          },
          "names": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The new names list, present only when `names` was provided in the request body."
          },
          "locations": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The new locations list, present only when `locations` was provided in the request body."
          },
          "custom_fields": {
            "type": "object",
            "description": "Echoes the custom_fields object exactly as sent, present only when `custom_fields` was provided in the request body. Note: any profile_field_N key NOT in this object has been NULLed in storage.",
            "additionalProperties": {
              "type": [
                "string",
                "number",
                "null"
              ]
            }
          }
        },
        "required": [
          "id"
        ]
      },
      "ContactCompanyResponse": {
        "type": "object",
        "description": "Response from the Attach Contact Company and Detach Contact Company endpoints.",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The canonical contact id (after resolving merged-profile aliases)."
          },
          "company_id": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The contact's company id after the operation. The attached company's id after Attach Contact Company; always `null` after Detach Contact Company."
          }
        },
        "required": [
          "id",
          "company_id"
        ]
      },
      "ContactPiiDeleteResponse": {
        "type": "object",
        "description": "Response from the Delete Contact PII endpoint. The scrub is queued, not yet complete.",
        "properties": {
          "contact_id": {
            "type": "integer",
            "description": "The canonical contact id (after resolving merged-profile aliases) whose PII was queued for deletion."
          },
          "status": {
            "type": "string",
            "enum": [
              "queued"
            ],
            "description": "Always `queued`."
          },
          "message": {
            "type": "string",
            "description": "Human-readable confirmation that the deletion has been queued."
          }
        },
        "required": [
          "contact_id",
          "status",
          "message"
        ]
      },
      "ContactPiiDeleteConflict": {
        "type": "object",
        "description": "409 response returned by the email-addressed contact endpoints (Delete Contact PII, Get Contact by Email) when the given email matches more than one distinct contact. No action is taken against any of the matched contacts.",
        "properties": {
          "message": {
            "type": "string",
            "description": "Error description explaining that multiple contacts matched."
          },
          "contact_ids": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Sorted list of canonical contact ids that matched the given email. Retry the request once per id."
          }
        },
        "required": [
          "message",
          "contact_ids"
        ]
      },
      "ContactConversionEvent": {
        "type": "object",
        "description": "A conversion event from the contact's journey.",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "conversion"
            ],
            "description": "Event type identifier."
          },
          "id": {
            "type": "integer",
            "description": "The unique conversion identifier."
          },
          "event_name": {
            "type": "string",
            "description": "The name of the conversion event (e.g. purchase, custom_event_1)."
          },
          "amount": {
            "type": [
              "number",
              "null"
            ],
            "description": "Transaction amount."
          },
          "event_time_utc": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp of when the conversion occurred (UTC)."
          },
          "event_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "The full URL where the conversion occurred."
          },
          "order_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Order identifier."
          },
          "order_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Order name or description."
          },
          "channel": {
            "type": "string",
            "enum": [
              "browser",
              "server"
            ],
            "description": "Whether the event was tracked via browser or server-side integration."
          },
          "integration": {
            "type": "string",
            "description": "Integration name for server-side events (e.g. Shopify, Stripe). Only present when channel is server."
          }
        },
        "required": [
          "type",
          "id",
          "event_name",
          "event_time_utc",
          "channel"
        ]
      },
      "ContactTouchpointEvent": {
        "type": "object",
        "description": "A touchpoint (ad click / visit) from the contact's journey.",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "touchpoint"
            ],
            "description": "Event type identifier."
          },
          "event_time_utc": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp of when the touchpoint occurred (UTC)."
          },
          "source": {
            "type": [
              "string",
              "null"
            ],
            "description": "Traffic source (e.g. facebook_ads, google_ads, organic)."
          },
          "touchpoint_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "The URL the user visited."
          },
          "referrer_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "The referring URL."
          },
          "ad_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Platform ad ID. Null for non-ad touchpoints."
          },
          "ad_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Ad name. Null for non-ad touchpoints."
          },
          "adset_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Platform ad set ID."
          },
          "adset_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Ad set name."
          },
          "campaign_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Platform campaign ID."
          },
          "campaign_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Campaign name."
          },
          "account_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Platform ad account ID."
          },
          "account_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Ad account name."
          }
        },
        "required": [
          "type",
          "event_time_utc"
        ]
      },
      "ContactListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Contact"
            }
          },
          "path": {
            "type": "string",
            "description": "The base URL path for the endpoint."
          },
          "per_page": {
            "type": "integer",
            "description": "Number of items per page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Cursor for the next page of results."
          },
          "next_page_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Full URL for the next page of results."
          },
          "prev_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Cursor for the previous page of results."
          },
          "prev_page_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Full URL for the previous page of results."
          }
        },
        "required": [
          "data",
          "path",
          "per_page",
          "next_cursor",
          "next_page_url",
          "prev_cursor",
          "prev_page_url"
        ]
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer"
      }
    }
  }
}
