---
title: "Create ad stats"
method: POST
path: "/ad_stats"
tags: ["Ads"]
---

# Create ad stats

`POST /ad_stats`

## Request

- Base URL: `https://api.whop.com/api/v1`
- URL: `https://api.whop.com/api/v1/ad_stats`
- Auth: HTTP bearer

Records a runner's stats for one of their ads in one hour, and pays them for the spend. Send the ad's totals so far for an hour that started in the last 24 hours; they replace what the ad held for that hour, and its ad group's and campaign's hours are rebuilt from their ads. The spend can go up but never down. Reporting on a campaign starts with the hour of its first recorded report; earlier hours are refused. The spend is recorded and paid exactly as sent, with no markup added, so send it with the runner's markup already applied. Takes the runner's Whop session, a user API key, or a user OAuth token with `ad_campaign:update`. A token without that scope gets a 403, and anyone not holding the ad's campaign gets a 404.

## Headers

- `Idempotency-Key` string

## Request body

- object
  - `ad_id` string, required: The ad's ID, prefixed `ad_`: the campaign's ad or the runner's copy of it.
  - `clicks` union: The ad's clicks in the hour so far, at most `impressions`. Zero when left out.
    - integer
    - string
  - `hour_started_at` string, date-time, required: Start of the hour, on the hour, within the last 24 hours.
  - `impressions` union: The ad's impressions in the hour so far. Zero when left out.
    - integer
    - string
  - `spend` union, required: The USD to be paid for the ad's hour so far, to the cent: what the ad spent plus any markup, such as 105.00 for 100.00 spent with a 5% markup.
    - number
    - string

## Response `200`

stats recorded

- AdStat
  - `ad_campaign_id` string, required: The ID of the ad's campaign, prefixed `adcamp_`.
  - `ad_group_id` string, required: The ID of the ad's ad group, prefixed `adgrp_`.
  - `ad_id` string, required: The ad's ID, prefixed `ad_`, as sent.
  - `clicks` integer, required: The ad's clicks in the hour.
  - `hour_started_at` string, required: Start of the hour, as an ISO 8601 timestamp.
  - `impressions` integer, required: The ad's impressions in the hour.
  - `spend` Money, required
    - `amount` string, required: The amount in major units, as an exact decimal string — `"10.00"` is ten dollars. A string so no float rounds it in transit.
    - `currency` string, required: Three-letter ISO 4217 currency code, lowercase.
    - `decimals` integer, required: How many decimal places the amount CARRIES — the precision the charge itself runs at.
    - `display_decimals` integer, required: How many decimal places to SHOW. Usually equal to `decimals`, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is `2` and `0`. Format the number in your own locale using this.

## Other responses

- `400`: more clicks than impressions
- `401`: Unauthorized
- `403`: a token without ad_campaign:update
- `404`: an ad the runner doesn't report on
- `409`: Conflict

## Changes

> 203 revisions in range; 1 not diffed.

- **2026-10-28** `596ade2123b6`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/whop/apis/whop-api/changes/ad_stats/post.md)

---

[API](https://skmtc.dev/whop/apis/whop-api.md) - [All operations](https://skmtc.dev/whop/apis/whop-api/llms.txt) - [OpenAPI document](https://skmtc.dev/whop/apis/whop-api/revisions/9993d9eaebc8?raw)
