---
title: "Create reach-frequency prediction"
method: POST
path: "/v1/ads/rf-predictions"
tags: ["Reach and Frequency"]
---

# Create reach-frequency prediction

`POST /v1/ads/rf-predictions`

Creates an R&F prediction. This is a QUOTE, nothing is bought and no ad entities are created.
Provide a date range plus exactly one of `budgetAmount` (Meta predicts reach) or `reach`
(Meta predicts the budget). The response carries the estimate and its allowed bounds
(min/max budget and reach). Predictions expire on their own; to buy, reserve one via
POST /v1/ads/rf-predictions/{predictionId}/reserve and pass the RESERVED id to
POST /v1/ads/create with `buyingType: "RESERVED"`.

Reservation campaigns reject automatic placements. Top-level `placements` wins; when it is
omitted, `targeting.placements` is used; when neither is set, placements default to
Facebook feed (+ Instagram stream when a linked IG professional account resolves).
Instagram placements require that IG account.

## Request body

- object
  - `accountId` string, required — Zernio SocialAccount id (posting or ads variant).
  - `adAccountId` string, required — Platform ad account id (Meta act_<n>, Google customer id, LinkedIn account id, ...).
  - `budgetAmount` number — Whole currency units. Exactly one of budgetAmount / reach.
  - `reach` integer — Target unique reach. Exactly one of budgetAmount / reach.
  - `startDate` string, date-time, required — Campaign window start (must be in the future).
  - `endDate` string, date-time, required
  - `frequencyCap` integer — Max impressions per person over the window.
  - `targeting` object — Canonical camelCase TargetingSpec (same shape as /v1/ads/create's `targeting`). Defaults to countries: [US].
  - `placements` object — Meta placements object (same shape as /v1/ads/create's `placements`).

## Response `201`

Prediction created (usually ready within seconds)

- object
  - `adAccountId` string
  - `currency` string
  - `prediction` RfPrediction — A Meta Reach & Frequency prediction. Money values in whole units of the ad account currency.
    - `predictionId` string
    - `status` string — ready | pending | failed:<meta code>
    - `budget` number, nullable — Quoted (or provided) lifetime budget for the window.
    - `reach` integer, nullable — Predicted (or requested) unique reach.
    - `impressions` integer, nullable
    - `minBudget` number, nullable — Meta's allowed lower bound for this spec.
    - `maxBudget` number, nullable
    - `minReach` integer, nullable
    - `maxReach` integer, nullable
    - `frequencyCap` integer, nullable
    - `startTime` integer, nullable — Unix seconds; the reserved window the R&F ad set will run on.
    - `stopTime` integer, nullable
    - `expiresAt` string, nullable — When the reservation's locked price expires (set after reserving).

## Other responses

- `400` — Invalid input, or Meta rejected the prediction; the message carries Meta's error
- `401` — Unauthorized
- `404` — The account or requested resource was not found or is not accessible. An account ID may have been disconnected and removed. Read GET /v1/accounts for current account IDs.
- `409` — The account exists but is inactive or needs reconnection. Reconnect it, then read GET /v1/accounts for its current account ID before retrying. Code: ads_connection_required.
- `422` — No Facebook Page resolved for the account
- `501` — Only supported on Meta (facebook/instagram)

## Changes

- **2026-09-16** `3e6ddf2a99ea` — 2 info
  - added the optional property `details/budgetScope` to the response with the `404` status
  - added the optional property `details/budgetScope` to the response with the `409` status
- **2026-09-15** `0dba7d004d75` — 4 info
  - added the optional property `details/quotaExhausted` to the response with the `404` status
  - added the optional property `details/quotaExhausted` to the response with the `409` status
  - added the optional property `details/quotaScope` to the response with the `404` status
  - added the optional property `details/quotaScope` to the response with the `409` status
- **2026-09-10** `e70ed06e7150` — 2 info
  - added the non-success response with the status `404`
  - added the non-success response with the status `409`

[Change history](https://skmtc.dev/zernio/apis/zernio-api/changes/v1/ads/rf-predictions/post.md)

---

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