# Create ads

Create a Microsoft Ads search campaign with its ad group, responsive search ad and keywords in one call.

import { Tab, Tabs } from 'fumadocs-ui/components/tabs';

`POST /v1/ads/create` creates the search campaign, its ad group, a responsive search ad and its keywords in one call.

## Create a campaign

Send `status: "PAUSED"` to create it paused. Without `status`, every level is switched on and the campaign starts spending once Microsoft approves the ad.

<Tabs items={['Node.js', 'Python', 'curl']}>
<Tab value="Node.js">
```typescript
import Zernio from '@zernio/node';

const zernio = new Zernio();

const { data: created } = await zernio.adcampaigns.createStandaloneAd({
  body: {
    accountId: '66b2e19d8c3f5a7e9d0b1c2d',
    adAccountId: '189372438',
    name: 'Planner launch',
    goal: 'traffic',
    status: 'PAUSED',
    budgetAmount: 5,
    budgetType: 'daily',
    headline: 'Plan Your Week in Minutes',
    body: 'Tasks, docs and meetings in one place. Free for teams of 5.',
    additionalHeadlines: ['Free for Teams of 5', 'One Planner for Everything'],
    linkUrl: 'https://example.com/planner',
    countries: ['US', 'CA'],
    keywords: ['team planner', { text: 'weekly planner app', matchType: 'PHRASE' }]
  }
});

console.log(created.ad.id);
```
</Tab>
<Tab value="Python">
```python
from zernio import Zernio

client = Zernio()

created = client.ad_campaigns.create_standalone_ad(
    account_id="66b2e19d8c3f5a7e9d0b1c2d",
    ad_account_id="189372438",
    name="Planner launch",
    goal="traffic",
    status="PAUSED",
    budget_amount=5,
    budget_type="daily",
    headline="Plan Your Week in Minutes",
    body="Tasks, docs and meetings in one place. Free for teams of 5.",
    additional_headlines=["Free for Teams of 5", "One Planner for Everything"],
    link_url="https://example.com/planner",
    countries=["US", "CA"],
    keywords=["team planner", {"text": "weekly planner app", "matchType": "PHRASE"}],
)

print(created["ad"]["id"])
```
</Tab>
<Tab value="curl">
```bash
curl -X POST "https://zernio.com/api/v1/ads/create" \
  -H "Authorization: Bearer $ZERNIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "accountId": "66b2e19d8c3f5a7e9d0b1c2d",
    "adAccountId": "189372438",
    "name": "Planner launch",
    "goal": "traffic",
    "status": "PAUSED",
    "budgetAmount": 5,
    "budgetType": "daily",
    "headline": "Plan Your Week in Minutes",
    "body": "Tasks, docs and meetings in one place. Free for teams of 5.",
    "additionalHeadlines": ["Free for Teams of 5", "One Planner for Everything"],
    "linkUrl": "https://example.com/planner",
    "countries": ["US", "CA"],
    "keywords": ["team planner", { "text": "weekly planner app", "matchType": "PHRASE" }]
  }'
```
</Tab>
</Tabs>

Response (`201`), trimmed:

```json
{
  "ad": {
    "id": "6ae0968fa23091cc35b72121",
    "name": "Planner launch",
    "platform": "microsoft",
    "status": "paused",
    "adType": "standalone",
    "goal": "traffic",
    "budget": { "amount": 5, "type": "daily" },
    "platformAdId": "74217415020506",
    "platformCampaignId": "571866721",
    "platformAdSetId": "1187474990051502",
    "platformAdAccountId": "189372438"
  }
}
```

`budgetAmount` is in whole units of the ad account's currency. `platformAdSetId` is the Microsoft ad group, and the ad name stays the `name` you sent: Microsoft has no ad name of its own.

Campaign and ad group names default to `<name> - Campaign` and `<name> - Ad Group`; send `campaignName` and `adSetName` to set them.

Every sample on the Microsoft Ads pages reuses the `zernio` and `client` constructors from this one. The `accountId` is the `microsoftads` account from [Connect](/platforms/microsoft-ads#connect).

## Ad copy

| Field | Rule |
|-------|------|
| `headline` | Required, the first headline, up to 30 characters |
| `additionalHeadlines` | Up to 14 more, each up to 30 characters |
| `body` | Required, the first description, up to 90 characters |
| `additionalDescriptions` | Up to 3 more, each up to 90 characters |
| `linkUrl` | Required, the landing page |

Microsoft needs at least 3 headlines and 2 descriptions. When you send fewer, Zernio fills the rest from the ad `name` and the landing page's host name.

## How it behaves

- `countries` (or `targeting.countries`) is required, so a campaign never serves everywhere.
- Each keyword is a string (match type `BROAD`) or `{ text, matchType }` with `EXACT`, `PHRASE` or `BROAD`.
- `startDate` and `endDate` set the ad group's schedule.
- If a step after the campaign fails, Zernio deletes the campaign it created, so a failed create leaves nothing behind.
- Microsoft reviews every new ad: it serves only once its editorial review passes, and a rejected ad reads `rejected`.

## If it fails

| Error | Cause | Fix |
|-------|-------|-----|
| `422` with `param: "targeting.countries"` | No countries sent | Send `countries`. |
| `422` with `param: "budget.type"` | A lifetime budget | Send `budgetType: "daily"`. |
| `422` with `param: "bidStrategy"` | A bid field sent | Leave bid fields out: campaigns use Maximize Clicks. |
| `422` with `param: "campaignType"` | A campaign type other than `search` | Omit `campaignType`. |
| `422` on `headline`, `body` or `linkUrl` | A required ad field is missing or the URL does not parse | Send all three. |
| `400` on `additionalHeadlines` or `additionalDescriptions` | A text over its character limit, or too many | Shorten it, or send fewer. |

## Related

- [Create standalone ad](/ad-campaigns/create-standalone-ad): every field of the request.
- [Targeting](/platforms/microsoft-ads/targeting): the countries a campaign takes.
- [Manage ads](/platforms/microsoft-ads/manage-ads): pause, resume, rebudget and delete.
- [Limits & errors](/platforms/microsoft-ads/reference): what Microsoft Ads does not support yet.