> ## Documentation Index
> Fetch the complete documentation index at: https://docs.apostra.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Upload context records

> Upload exogenous market conditions the engine should partial out

`POST /api/v2/buyer/advertisers/{advertiserId}/context-records`

Uploads exogenous context data — promos, weather, competitor activity, seasonality — so the learning engine can partial these effects out when estimating incremental impact. Each record covers one geo and time window. Up to 5,000 records per call.

## Request

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.apostra.com/api/v2/buyer/advertisers/12345/context-records \
    -H "Authorization: Bearer $SCOPE3_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "records": [
        {
          "geo": "US-CA",
          "timeWindowStart": "2026-03-01",
          "timeWindowEnd": "2026-03-07",
          "promoActive": true,
          "promoType": "site_wide_15_off",
          "seasonalityIndex": 1.12,
          "flightStatus": "active"
        }
      ]
    }'
  ```
</CodeGroup>

## Parameters

| Field | Type | Required | Notes |
| - | - | - | - |
| `advertiserId` | string | Yes | Path parameter — the owning advertiser |
| `records` | array | Yes | 1–5000 records |
| `records[].geo` | string | Yes | Geo identifier (e.g. `US-CA`) |
| `records[].timeWindowStart` | string | Yes | Date `YYYY-MM-DD` |
| `records[].timeWindowEnd` | string | Yes | Date `YYYY-MM-DD` |
| `records[].promoActive` | boolean | No | Whether a promo ran (default `false`) |
| `records[].promoType` | string | No | Free-text promo descriptor |
| `records[].temperatureAvg` | number | No | Average temperature for weather effects |
| `records[].competitorActivity` | object | No | Free-form competitor signals |
| `records[].seasonalityIndex` | number | No | Seasonality multiplier |
| `records[].flightStatus` | enum | No | `active`, `dark`, `pre_flight`, `post_flight` (default `active`) |

## Response

```json theme={null}
{
  "recordsUploaded": 1
}
```

Returns the count of records uploaded. The endpoint upserts on `(account, advertiser, geo, time window)`, so re-uploading the same key updates in place.

## Errors

* `400 VALIDATION_ERROR` — empty `records`, more than 5,000 records, a missing required field, or a malformed date.
* `404 NOT_FOUND` — `advertiserId` does not exist or is not visible to the authenticated account.

See [Errors](/v2/reference/errors) for the full error contract.

## Related

<CardGroup cols={2}>
  <Card title="Measurement tasks" href="/v2/buyer/measurement/tasks" icon="list-check">
    All measurement operations
  </Card>

  <Card title="Measurement overview" href="/v2/guides/measurement-incrementality" icon="chart-line">
    Pipeline, belief state, and concepts
  </Card>

  <Card title="Upload measurement records" href="/v2/buyer/measurement/tasks/upload-measurement-records" icon="upload">
    Upload outcome records
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.