{
  "openapi": "3.1.0",
  "info": {
    "title": "ATTEX export API",
    "version": "1.0.0",
    "description": "Create export jobs for ATTEX impressions, poll them, and download the files they produce."
  },
  "servers": [
    {
      "url": "https://global-api.attentionpanel.com"
    }
  ],
  "security": [
    {
      "ApiKey": []
    }
  ],
  "paths": {
    "/impressions/export": {
      "post": {
        "operationId": "createExport",
        "summary": "Create an export",
        "description": "Starts an export job for one platform, market and inclusive range of UTC dates.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateExportRequest"
              },
              "example": {
                "device": "mobile",
                "market": "semarket",
                "from_date": "2026-10-01",
                "to_date": "2026-10-07"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The job was created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateExportResponse"
                },
                "example": {
                  "export_id": "acme_3f6c1d2e-8b4a-4c55-9a77-2d1f0e9b6a10",
                  "status": "RUNNING"
                }
              }
            }
          },
          "400": {
            "description": "Bad request. `message` holds one of the codes below.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              {
                "code": "(validation message)",
                "cause": "Missing or unknown field, bad date, or `from_date` after `to_date`."
              },
              {
                "code": "FROM_DATE_NOT_ALLOWED",
                "cause": "`from_date` is before the key's earliest allowed date."
              },
              {
                "code": "MAX_PARALLEL_RUNS_LIMIT_REACHED",
                "cause": "The key already has its maximum number of running jobs for this platform, market and version."
              },
              {
                "code": "V2_FROM_DATE_NOT_AVAILABLE",
                "cause": "`version` `v2` with `from_date` before the first day of v2 data, which `available_from` gives (`YYYY-MM-DD`)."
              },
              {
                "code": "V2_ONLY_AVAILABLE_FOR_MOBILE",
                "cause": "`version` `v2` with a device other than `mobile`."
              }
            ]
          },
          "401": {
            "description": "No `Authorization` header."
          },
          "403": {
            "description": "Invalid key, or platform or market outside its entitlements."
          }
        }
      }
    },
    "/exports/{export_id}": {
      "get": {
        "operationId": "getExport",
        "summary": "Get an export",
        "description": "Returns the job's state, and the files once it has succeeded.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ExportId"
          }
        ],
        "responses": {
          "200": {
            "description": "The job's current state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Export"
                },
                "example": {
                  "status": "SUCCEEDED",
                  "download_urls": [
                    "https://example.invalid/year=2026/month=10/day=01/part-00000.json.gz?X-Amz-Signature=…"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request. `message` holds one of the codes below.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              {
                "code": "EXPORT_EXPIRED",
                "cause": "The download URLs are older than 24 hours. Create a new export."
              }
            ]
          },
          "404": {
            "description": "Unknown `export_id`, or one created with another key."
          }
        }
      }
    },
    "/exports/{export_id}/cancel": {
      "post": {
        "operationId": "cancelExport",
        "summary": "Cancel an export",
        "description": "Stops a running job.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ExportId"
          }
        ],
        "responses": {
          "200": {
            "description": "The job was cancelled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CancelExportResponse"
                },
                "example": {
                  "export_id": "acme_3f6c1d2e-8b4a-4c55-9a77-2d1f0e9b6a10",
                  "status": "CANCELLED"
                }
              }
            }
          },
          "400": {
            "description": "Bad request. `message` holds one of the codes below.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              {
                "code": "EXPORT_NOT_IN_CANCELABLE_STATE",
                "cause": "The job is no longer running."
              }
            ]
          },
          "404": {
            "description": "Unknown `export_id`, or one created with another key."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "Your API key, sent as is, with no scheme prefix."
      }
    },
    "parameters": {
      "ExportId": {
        "name": "export_id",
        "in": "path",
        "required": true,
        "description": "The `export_id` returned by Create an export. URL-encode it.",
        "schema": {
          "type": "string"
        }
      }
    },
    "schemas": {
      "CreateExportRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "device",
          "market",
          "from_date",
          "to_date"
        ],
        "properties": {
          "device": {
            "type": "string",
            "enum": [
              "mobile",
              "desktop"
            ],
            "description": "The platform."
          },
          "market": {
            "type": "string",
            "enum": [
              "semarket",
              "nomarket",
              "dkmarket",
              "fimarket"
            ],
            "description": "The market."
          },
          "from_date": {
            "type": "string",
            "format": "date",
            "description": "`YYYY-MM-DD`, inclusive. Not before the key's earliest allowed date."
          },
          "to_date": {
            "type": "string",
            "format": "date",
            "description": "`YYYY-MM-DD`, inclusive. Not before `from_date`."
          },
          "include_html_metadata": {
            "type": "boolean",
            "default": false,
            "description": "Desktop only. Adds `html_metadata` when the key is entitled to it."
          },
          "version": {
            "type": "string",
            "enum": [
              "v1",
              "v2"
            ],
            "description": "Mobile only. The mobile data version; `v1` when omitted. `v2` data starts on a date set per deployment: an earlier `from_date` returns 400 `V2_FROM_DATE_NOT_AVAILABLE` with that date in `available_from`."
          }
        }
      },
      "CreateExportResponse": {
        "type": "object",
        "required": [
          "export_id",
          "status"
        ],
        "properties": {
          "export_id": {
            "type": "string",
            "description": "Use in the other endpoints. URL-encode it in paths."
          },
          "status": {
            "type": "string",
            "const": "RUNNING",
            "description": "Always `RUNNING`."
          },
          "version": {
            "type": "string",
            "enum": [
              "v1",
              "v2"
            ],
            "description": "The data version the job exports."
          }
        }
      },
      "Export": {
        "type": "object",
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "RUNNING",
              "SUCCEEDED",
              "FAILED",
              "CANCELLED"
            ],
            "description": "Only `RUNNING` changes."
          },
          "version": {
            "type": "string",
            "enum": [
              "v1",
              "v2"
            ],
            "description": "The data version the job exports."
          },
          "download_urls": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            },
            "description": "On `SUCCEEDED`. Presigned, one per file, valid 24 hours after completion. Send no `Authorization` header to them."
          },
          "failure_reason": {
            "type": "string",
            "enum": [
              "NO_DATA",
              "INTERNAL_ERROR"
            ],
            "description": "On `FAILED`: `NO_DATA` (no rows for the request) or `INTERNAL_ERROR`."
          }
        }
      },
      "CancelExportResponse": {
        "type": "object",
        "required": [
          "export_id",
          "status"
        ],
        "properties": {
          "export_id": {
            "type": "string",
            "description": "The cancelled job."
          },
          "status": {
            "type": "string",
            "const": "CANCELLED",
            "description": "Always `CANCELLED`."
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "statusCode",
          "message"
        ],
        "properties": {
          "statusCode": {
            "type": "integer"
          },
          "message": {
            "type": "string",
            "description": "The code to branch on, for example `FROM_DATE_NOT_ALLOWED`."
          },
          "available_from": {
            "type": "string",
            "format": "date",
            "description": "With `V2_FROM_DATE_NOT_AVAILABLE`: the first day of v2 data."
          }
        }
      }
    }
  }
}
