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

# Ad groups and ads

> Create and manage the ad groups and ads of a campaign.

A campaign contains ad groups, and an ad group contains ads. An ad group has one of two types:

* **`generative`** (default): Gravity makes the ads for the group from your `context` and `ad_prompt`. If you send authored `ads`, the response is `422`.
* **`manual`**: you write the ads in the `ads` array or with the ads endpoints below. You cannot change generated ads. You can change or archive only manual ads.

> [!WARNING]
>
> Users see the `brand_name` of an ad group. It is the brand next to the ad. It is also the title of the ad when the ad has no `headline`. If you create groups for your own users, put the brand of the end advertiser in `brand_name`. Do not use your internal account or workspace label (for example `"Jane Doe on YourApp"`), because Gravity shows that text to readers. A change to `brand_name` does not change the headlines that Gravity already generated for the group. To change what Gravity serves, create a new group, or set a `headline` on a manual ad.

These endpoints use the same code and ownership checks as the Gravity dashboard. They apply only to the account of your API key.

## GET `/advertiser-dashboard/ad-groups`

List your ad groups. Each group contains its ads, up to 100 for each group. `ads_total` gives the full count. Without `campaign_id`, the list has at most 2,000 ad groups.

**campaign\_id** `string`

Show only one campaign.

**include\_archived** `boolean` (default: false)

Include archived groups.

```bash Request theme={null}
curl "https://platform.trygravity.com/advertiser-dashboard/ad-groups?campaign_id=camp-456" \
  -H "X-API-Key: YOUR_API_KEY"
```

```json Response theme={null}
[
  {
    "id": "adg-789",
    "campaign_id": "camp-456",
    "name": "Summer Sale (Generative)",
    "group_type": "generative",
    "status": "active",
    "context": "Summer footwear sale, focus on running shoes",
    "landing_page": null,
    "daily_budget": null,
    "auto_optimize_budget": true,
    "max_cpc": null,
    "allowed_countries": null,
    "allowed_devices": null,
    "sort_order": 0,
    "created_at": "2026-07-23 00:00:00",
    "updated_at": "2026-07-23 00:00:00",
    "ads": [],
    "ads_total": 0
  }
]
```

## POST `/advertiser-dashboard/ad-groups`

Create an ad group in one of your campaigns.

**campaign\_id** `string` *required*

The campaign for the group. Your account must own it.

**name** `string` *required*

The ad group name, at most 500 characters.

**group\_type** `string` (default: generative)

`generative` or `manual`.

**status** `string` (default: active)

`active`, `paused`, or `archived`.

**context** `string`

The target context. Gravity uses it to match conversations, and to make ads for generative groups.

**negative\_context** `string`

The conversations to avoid.

**ad\_prompt** `string`

A prompt that guides the ad generation (generative groups).

**landing\_page** `string`

The default landing page for the ads of the group.

**brand\_name** `string`

The brand that you advertise. Users see it. Gravity uses it as the title of an ad that has no `headline`. Send the product or company that you advertise (`"Acme"`). Do not send an internal account, workspace, or person label (`"Jane Doe on YourApp"`). If you do not send it, Gravity uses the host name of `landing_page`. At most 500 characters.

**image\_url** `string`

The default image for the ads of the group, for example the brand logo or a product image. An ad uses it when the ad has no `image_url`. A generated ad copies the group image when Gravity generates the ad. So a later change to the group `image_url` does not replace an image that is already on a generated ad. The URL must point to a public PNG, JPEG, GIF, or WebP file (not a web page) of 10 MB or less. Some delivery networks need an image on each ad. See [Ad images](#ad-images).

**daily\_budget** `integer`

Legacy stored field. Set the delivery budget on the campaign.

**max\_cpc** `number`

The maximum cost per click for the group, in dollars. It applies on a click-billed (`cpc`) campaign. Gravity ignores it on an impression-billed campaign. Gravity reads `0` as no value.

**allowed\_countries** `array`

The countries to target for this group.

**allowed\_devices** `array`

The platforms to target for this group.

**ads** `array`

Authored ads (manual groups only). Each ad accepts `name`, `headline` (at most 80 characters), `copy` (at most 500 characters), `cta` (at most 80 characters), `description`, `landing_page`, `image_url`, and `status`.

The response is `201` with the new group and its ads, in the same shape as the list response. If you send authored `ads` to a generative group, the response is `422`.

```bash Request theme={null}
curl -X POST https://platform.trygravity.com/advertiser-dashboard/ad-groups \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "campaign_id": "camp-456",
    "name": "Trail Runners (Manual)",
    "group_type": "manual",
    "context": "Trail running gear",
    "brand_name": "Acme",
    "ads": [
      {
        "headline": "Grip Every Trail",
        "copy": "Trail shoes built for mud, rock, and rain.",
        "cta": "Shop Trail",
        "landing_page": "https://acme.com/trail"
      }
    ]
  }'
```

### Ad images

Some delivery networks need an image on each ad. Gravity uses the first image of this list that has a value:

1. The `image_url` of the ad. An authored ad gets it from your request. A generated ad copies the `image_url` of the group when Gravity generates the ad.
2. The current `image_url` of the ad group.
3. The custom favicon of the campaign.
4. A favicon that Gravity finds for the domain of the landing page. This lookup fails for many domains, so do not depend on it.

If no image is available, Gravity does not submit the ad. The campaign shows `ad_image_required` (and `ad_sync_failed`) in `delivery_issues`. The `network_review.reason` of the ad is: "The delivery network requires an image for this ad. Set image\_url on the ad or its ad group to resubmit it."

To fix it, do one of these steps:

* Set `image_url` on the ad group with `PATCH /advertiser-dashboard/ad-groups/{ad_group_id}`.
* Set `image_url` on an authored ad with `PATCH /advertiser-dashboard/ads/{ad_id}`.

Gravity then submits the failed ads again. You cannot change a generated ad directly. A generated ad with no image of its own uses the new `image_url` of the group.

## GET `/advertiser-dashboard/ad-groups/{ad_group_id}`

Get one ad group with its ads. If the ad group is not in your account, the response is `404`.

## PATCH `/advertiser-dashboard/ad-groups/{ad_group_id}`

Change the fields of an ad group. Send only the fields that you want to change. You cannot change a `manual` group to `generative` while it has manual ads that are not archived (`422`). When you set or change `image_url`, Gravity submits the failed ads of the group again.

```bash Request theme={null}
curl -X PATCH https://platform.trygravity.com/advertiser-dashboard/ad-groups/adg-789 \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"status": "paused"}'
```

## DELETE `/advertiser-dashboard/ad-groups/{ad_group_id}`

Archive an ad group and its ads. The response is `204`.

## POST `/advertiser-dashboard/ad-groups/{ad_group_id}/ads`

Write an ad in a **manual** group. The response is `201` with the new ad. On a generative group, the response is `422`.

```bash Request theme={null}
curl -X POST https://platform.trygravity.com/advertiser-dashboard/ad-groups/adg-790/ads \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "headline": "50% Off Running Shoes",
    "copy": "Summer sale on all running shoes.",
    "cta": "Shop Now",
    "landing_page": "https://acme.com/summer"
  }'
```

```json Response 201 theme={null}
{
  "id": "ad-901",
  "ad_group_id": "adg-790",
  "campaign_id": "camp-456",
  "name": null,
  "headline": "50% Off Running Shoes",
  "copy": "Summer sale on all running shoes.",
  "cta": "Shop Now",
  "description": null,
  "landing_page": "https://acme.com/summer",
  "image_url": null,
  "source": "manual",
  "status": "active",
  "review_status": "pending",
  "created_at": "2026-07-23 00:00:00",
  "updated_at": "2026-07-23 00:00:00"
}
```

## GET `/advertiser-dashboard/ads/{ad_id}`

Get one ad. If the ad is not in your account, the response is `404`.

## PATCH `/advertiser-dashboard/ads/{ad_id}`

Change a manual ad (`headline`, `copy`, `cta`, `landing_page`, `status`, and the other ad fields). You cannot change generated ads. For a generated ad, the response is `422`.

## DELETE `/advertiser-dashboard/ads/{ad_id}`

Archive a manual ad. The response is `204`. For a generated ad, the response is `422`.


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