Create a new campaign. Campaigns measure the impact of a change — promotion, layout shift, staff schedule — by comparing a **test period** against a **control period** across one or more locations.

> **Date format:** campaign endpoints (`testPeriod`, `controlPeriod`) require **full ISO 8601 with timezone**, e.g. `2024-04-14T10:00:00.000Z`. Date-only strings are rejected.

## Body parameters

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | yes | Display name |
| `metric` | object | yes | `{ key, display }` plus optional `type`, `unitType`. `key` is the metric identifier (e.g. `entries`); `display` is the UI label |
| `campaignUplift` | number | yes | Expected uplift as a **proportion** (e.g. `0.1` = 10%), not a percent |
| `taxonomies` | string\[\] | yes | Array of taxonomy path strings (may be `[]`) |
| `lineTaxonomies` | string\[\] | yes | Array of taxonomy path strings (may be `[]`) |
| `testLocations` | string\[\] | yes | Array of location IDs to include in the test group |
| `testPeriod` | object | yes | See **Period shape** below |
| `controlPeriod` | object | no | Same shape as `testPeriod`. When present, `controlPeriod.active: boolean` is required |
| `selectedBreakdowns` | object\[\] | yes | Array of `{ key, values }` objects — see **selectedBreakdowns** below |
| `description` | string | no | Max 1000 characters |
| `controlLocations` | string\[\] | no | Array of location IDs for the control group |

### Period shape (`testPeriod` / `controlPeriod`)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `selectedPreset` | string | yes | Opaque label (e.g. "custom", "last-30-days"). Validated only as a string — not against a closed list |
| `selectedDates` | `{ start, end }` | yes | ISO 8601 timestamps with timezone |
| `customPeriodDates` | `{ start, end }` | no | Optional alongside `selectedDates` |
| `active` | boolean | yes (control only) | Required on `controlPeriod` |

### Taxonomies and line taxonomies

`taxonomies` is an array of zone-path strings (e.g. `Service:Checkout`, `Products:Clothing`) the campaign should track on area-based metrics. `lineTaxonomies` does the same for line-based metrics (entries, passers-by, capture rate, etc.). Both arrays may be empty (`[]`) for location-wide metrics that don’t filter by zone.

These values map onto the zones and lines you’ve configured for each recording. To enumerate what’s available for your locations, query: Area definitions and Line definitions. The full list of metric routes is in the Metrics API overview.

### `selectedBreakdowns`

An array of `{ key, values }` objects — **not** a flat string array.

| `key` | Valid `values` |
| --- | --- |
| `"ages"` | `"0-15"`, `"16-24"`, `"25-34"`, `"35-44"`, `"45-54"`, `"55-64"`, `"65-100"` |
| `"genders"` | `"male"`, `"female"` |
| `"roles"` | `"customer"`, `"staff"`, `"customer-customer"`, `"customer-staff"`, `"staff-staff"` |
| `""` | `"all visitors"` — the “all visitors combined” form |

## Example request

```
POST https://api.auravisionlabs.com/v1/campaign
Authorization: Bearer <your_token>
Content-Type: application/json
```

```
{
  "name": "Summer Promotion",
  "metric": { "key": "entries", "display": "Entries" },
  "campaignUplift": 0.1,
  "taxonomies": [],
  "lineTaxonomies": [],
  "testLocations": ["64a1b2c3d4e5f6a7b8c9d0e3"],
  "testPeriod": {
    "selectedPreset": "custom",
    "selectedDates": {
      "start": "2024-06-01T00:00:00.000Z",
      "end":   "2024-06-30T23:59:59.999Z"
    }
  },
  "controlPeriod": {
    "selectedPreset": "custom",
    "selectedDates": {
      "start": "2024-05-01T00:00:00.000Z",
      "end":   "2024-05-31T23:59:59.999Z"
    },
    "active": true
  },
  "selectedBreakdowns": [
    { "key": "genders", "values": ["male", "female"] }
  ]
}
```

## Example response

Returns `201 Created` with the full campaign object:

```
{
  "id": "64a1b2c3d4e5f6a7b8c9d0e7",
  "organisationId": "64a1b2c3d4e5f6a7b8c9d0e2",
  "name": "Summer Promotion",
  "metric": { "key": "entries", "display": "Entries" },
  "campaignUplift": 0.1,
  "taxonomies": [],
  "lineTaxonomies": [],
  "testLocations": ["64a1b2c3d4e5f6a7b8c9d0e3"],
  "controlLocations": [],
  "testPeriod": {
    "selectedPreset": "custom",
    "selectedDates": { "start": "2024-06-01T00:00:00.000Z", "end": "2024-06-30T23:59:59.999Z" }
  },
  "controlPeriod": {
    "selectedPreset": "custom",
    "selectedDates": { "start": "2024-05-01T00:00:00.000Z", "end": "2024-05-31T23:59:59.999Z" },
    "active": true
  },
  "selectedBreakdowns": [{ "key": "genders", "values": ["male", "female"] }],
  "testLocationsExcluded": false,
  "controlLocationsExcluded": false,
  "created": "2024-04-15T10:30:00.000Z",
  "updatedAt": "2024-04-15T10:30:00.000Z"
}
```
