Skip to main content
POST
The primary ad endpoint. Send conversation messages and get back a contextually matched ad with generated creative.

Headers

string
required
Your Gravity API key. Format: Bearer <key>

Body

array
required
Conversation history. Array of {role, content} message objects. The engine uses the last few messages for contextual matching.
string
required
Session identifier. Used for frequency capping, experiment bucketing, and reporting. If the Gravity pixel is installed and you’re on @gravity-ai/api ≥ 1.1.7, the SDK auto-forwards the pixel’s gr_sess_-prefixed session ID (30-min idle timeout, 1-day max) via window.gravityPixel.getSessionId(). Pass your own sessionId to override if you have a better session scope.
array
required
Ad placement configuration. 1–10 placements per request.
object
Optional. User context for targeting and attribution. All fields are optional on the wire — the engine accepts any shape and passes extras through.Extra fields (gender, age, subscription tier, interests, etc.) are accepted and stored as request context.
object
required
End-user device signals. ip and ua are required — requests missing either are rejected with HTTP 400 (see Errors). They power fraud/bot detection plus the Device and Geography breakdowns in your dashboard. The browser SDK auto-populates them via gravityContext(); server-side callers must forward the client-collected device (the request reaching Gravity otherwise carries your server’s UA/IP, not the end user’s).Extra fields (timezone, locale, browser, device_model, …) are accepted and stored. Native-app/non-browser clients should send their real client UA (CFNetwork/Darwin, okhttp, ktor-client, …) plus the end user’s IP. See Request ads → Device signals.
number
Optional. Minimum relevancy threshold, 0.0–1.0. When omitted, the engine falls back to the publisher baseline configured in your dashboard. Both SDKs default to 0.2.
array
Optional. Array of topic strings to exclude from matching (e.g. ["politics"]).
boolean
default:"false"
Optional. When true, returns test creative and skips billing/metrics. The SDKs set this from the inverse of their production flag.
string
Optional. The server-rendered design vocabulary your client supports. Official SDKs set this automatically.Set supportsSpec: false to opt out of server-rendered designs. The legacy supportsSpec: true value is treated as web support.
Optional. Privacy/consent signals for the end user. When omitted, behavior is unchanged from today.When gdprApplies is true and no valid tcfString is present, the engine serves contextual-only ads: it skips all processing keyed to pseudonymous user identifiers for that request (personalization, identity-keyed telemetry). Contextual matching — Gravity’s core model — needs no personal data, so ads still serve.

Response

On a successful match the endpoint returns HTTP 200 with a JSON array of ad objects — one per requested placement:
The SDKs wrap this array in a convenience object — { ads, status, elapsed } in JS, AdResult(ads, status, elapsed_ms, ...) in Python — but that envelope is SDK-only and does not appear on the wire.

Ad object

Null fields are omitted from the response.

renderer_spec

Gravity configures server-rendered designs per placement. When a compatible design is available, the response includes renderer_spec; otherwise the SDK uses its built-in card. Official SDKs handle this automatically. Contact support@trygravity.ai to configure a custom placement design. When an experiment is active, the ad object also includes: Experiment identity is already baked into impUrl and clickUrl — downstream analytics join automatically.
Always use clickUrl for ad links (not url directly) and fire impUrl when the ad becomes visible. This ensures accurate tracking and billing.

No ad available

When no ad matches the context (or the request is filtered as a bot, times out, or hits an unrecoverable error), the endpoint returns an HTTP 204 No Content with an empty body — there is no JSON payload. Your UI should gracefully hide the slot in that case.

Errors

Requests missing required fields are rejected with HTTP 400 and a JSON body naming each missing field. device.ip and device.ua are validated on every ad request (blank/whitespace-only values count as missing):
Fix the request by forwarding the end user’s real IP and User-Agent — see Request ads → Forwarding device server-side.