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

# Create ad

> Create an ad under a Targeter campaign on the publisher

## Overview

Create an ad in the publisher system. Targeter sends the campaign, office, flight, targeting, goal, platforms, and creatives. You generate `ad_id` and return the initial `status` (typically `pending_review` or `scheduled`).

Resolve [`office_id`](/integrations/offices/get) and [`publisher_platforms`](/integrations/platforms/get) before calling this endpoint.

At least one creative in `material` is required: `images`, `videos`, or `html5`.

## Request

### Headers

* `Authorization: Bearer {token}` (required)
* `Content-Type: application/json`

### Body Parameters

<ParamField path="campaign_id" type="string" required>
  Targeter campaign id this ad belongs to. Store and return it unchanged.
</ParamField>

<ParamField path="office_id" type="string" required>
  Publisher office id from [Create office](/integrations/offices/create) or [Get office ID](/integrations/offices/get)
</ParamField>

<ParamField path="name" type="string" required>
  Ad name / title (for example a property address)
</ParamField>

<ParamField path="budget" type="number" required>
  Spend cap for the ad
</ParamField>

<ParamField path="target_location" type="object" required>
  Geographic targeting
</ParamField>

<ParamField path="target_location.country" type="string" required>
  ISO 3166-1 alpha-2 country code
</ParamField>

<ParamField path="target_location.regions" type="string[]">
  Region or county names
</ParamField>

<ParamField path="target_location.lat" type="number" required>
  Latitude of the targeting centre
</ParamField>

<ParamField path="target_location.long" type="number" required>
  Longitude of the targeting centre
</ParamField>

<ParamField path="target_location.radius_km" type="number">
  Optional radius in kilometres around `lat` and `long`
</ParamField>

<ParamField path="start_date" type="string" required>
  When the ad may start delivering (inclusive). UTC ISO 8601 date-time.
</ParamField>

<ParamField path="end_date" type="string" required>
  When the ad must stop delivering (inclusive). UTC ISO 8601 date-time. Must be on or after `start_date`.
</ParamField>

<ParamField path="goal_config" type="object" required>
  What Targeter is optimizing for
</ParamField>

<ParamField path="goal_config.objective" type="string" required>
  `traffic`, `conversions`, `awareness`, or `leads`
</ParamField>

<ParamField path="goal_config.optimization_event" type="string">
  `impression`, `link_click`, `landing_page_view`, `lead`, or `purchase`
</ParamField>

<ParamField path="publisher_platforms" type="string[]" required>
  Platform ids from [Get publisher platforms](/integrations/platforms/get). At least one required.
</ParamField>

<ParamField path="material" type="object" required>
  Landing page and creatives
</ParamField>

<ParamField path="material.target_url" type="string" required>
  Landing page URL for the ad
</ParamField>

<ParamField path="material.images" type="string[]">
  Publicly reachable image URLs
</ParamField>

<ParamField path="material.videos" type="string[]">
  Publicly reachable video URLs
</ParamField>

<ParamField path="material.html5" type="string[]">
  Publicly reachable HTML5 creative URLs
</ParamField>

### Example Request

```bash theme={null}
curl -X POST "https://publisher.example.com/v1/ads" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "campaign_id": "AbC123xyz",
    "office_id": "off_8k2mQx",
    "name": "Majorstuenveien 14",
    "budget": 5000,
    "target_location": {
      "country": "NO",
      "lat": 59.9294,
      "long": 10.7166,
      "radius_km": 10
    },
    "start_date": "2026-08-20T00:00:00Z",
    "end_date": "2026-09-03T23:59:59Z",
    "goal_config": {
      "objective": "traffic",
      "optimization_event": "link_click"
    },
    "publisher_platforms": ["drammens_tidende", "nettavisen", "romerikes_blad"],
    "material": {
      "target_url": "https://megler.no/eiendom/123",
      "images": ["https://example.com/property-photo.jpg"],
      "videos": ["https://example.com/property-tour.mp4"],
      "html5": ["https://example.com/creatives/majorstuenveien-14.html"]
    }
  }'
```

## Response

### Success (201)

Returns the created ad, including the publisher-generated `ad_id` and initial `status`.

<ResponseField name="ad_id" type="string">
  Publisher-generated ad id. Targeter uses this on all later ad calls.
</ResponseField>

<ResponseField name="status" type="string">
  `draft`, `pending_review`, `scheduled`, `active`, `paused`, `completed`, `rejected`, or `error`
</ResponseField>

```json theme={null}
{
    "ad_id": "ad_9pL2wR",
    "campaign_id": "AbC123xyz",
    "office_id": "off_8k2mQx",
    "name": "Majorstuenveien 14",
    "status": "pending_review",
    "budget": 5000,
    "target_location": {
        "country": "NO",
        "lat": 59.9294,
        "long": 10.7166,
        "radius_km": 10
    },
    "start_date": "2026-08-20T00:00:00Z",
    "end_date": "2026-09-03T23:59:59Z",
    "goal_config": {
        "objective": "traffic",
        "optimization_event": "link_click"
    },
    "publisher_platforms": ["drammens_tidende", "nettavisen", "romerikes_blad"],
    "material": {
        "target_url": "https://megler.no/eiendom/123",
        "images": ["https://example.com/property-photo.jpg"],
        "videos": ["https://example.com/property-tour.mp4"],
        "html5": ["https://example.com/creatives/majorstuenveien-14.html"]
    },
    "created_at": "2026-08-19T08:12:00Z",
    "updated_at": "2026-08-19T08:12:00Z"
}
```

## Error Responses

### 400 - Invalid request payload

```json theme={null}
{
    "error": "Invalid request payload",
    "details": [
        {
            "path": ["material", "target_url"],
            "message": "Target URL is required"
        }
    ]
}
```

Reject the request if `end_date` is before `start_date`, if `publisher_platforms` is empty, or if `material` has no `images`, `videos`, or `html5`.

### 401 - Unauthorized

```json theme={null}
{
    "error": "Missing or invalid Authorization header"
}
```

### 404 - Office not found

```json theme={null}
{
    "error": "Office not found"
}
```

### 500 - Server Error

```json theme={null}
{
    "error": "Unexpected server error. Please try again later."
}
```


## OpenAPI

````yaml integrations/openapi.json POST /ads
openapi: 3.1.0
info:
  title: Targeter Ideal Publisher API
  description: >-
    Contract Targeter expects from publisher and media platforms it creates ads
    on and fetches insights from. Implement these endpoints so Targeter can
    manage offices, ads, and reporting against your system.
  version: 1.0.0
  contact:
    name: Targeter Integration Support
servers:
  - url: https://{publisher_host}/v1
    description: Publisher API host (provided during integration setup)
    variables:
      publisher_host:
        default: publisher.example.com
security:
  - BearerAuth: []
tags:
  - name: Offices
    description: Broker or advertiser offices that ads are billed and attributed to
  - name: Ads
    description: Create, update, pause, resume, and delete ads
  - name: Insights
    description: Performance reporting for ads Targeter has created
  - name: Platforms
    description: Publisher channels available for delivery
paths:
  /ads:
    post:
      tags:
        - Ads
      summary: Create ad
      description: >-
        Create an ad under a Targeter campaign. At least one creative in
        `material` is required (image, video, or HTML5). Return the
        publisher-generated `ad_id` and initial status.
      operationId: createAd
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateAdRequest'
      responses:
        '201':
          description: Ad created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Ad'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: Referenced office or campaign not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Office not found
        '500':
          $ref: '#/components/responses/ServerError'
components:
  schemas:
    CreateAdRequest:
      type: object
      required:
        - campaign_id
        - office_id
        - name
        - budget
        - target_location
        - start_date
        - end_date
        - goal_config
        - publisher_platforms
        - material
      properties:
        campaign_id:
          type: string
          description: Targeter campaign id this ad belongs to
          example: AbC123xyz
        office_id:
          type: string
          description: Publisher office id from `POST /offices` or `GET /offices`
          example: off_8k2mQx
        name:
          type: string
          description: Ad name / title
          example: Majorstuenveien 14
        budget:
          $ref: '#/components/schemas/Budget'
        target_location:
          $ref: '#/components/schemas/TargetLocation'
        start_date:
          type: string
          format: date-time
          example: '2026-08-20T00:00:00Z'
        end_date:
          type: string
          format: date-time
          example: '2026-09-03T23:59:59Z'
        goal_config:
          $ref: '#/components/schemas/GoalConfig'
        publisher_platforms:
          type: array
          minItems: 1
          items:
            type: string
          example:
            - drammens_tidende
            - nettavisen
            - romerikes_blad
        material:
          $ref: '#/components/schemas/Material'
    Ad:
      type: object
      required:
        - ad_id
        - campaign_id
        - office_id
        - name
        - status
        - budget
        - target_location
        - start_date
        - end_date
        - goal_config
        - publisher_platforms
        - material
      properties:
        ad_id:
          type: string
          description: Publisher-generated ad id
          example: ad_9pL2wR
        campaign_id:
          type: string
          description: Targeter campaign id this ad belongs to
          example: AbC123xyz
        office_id:
          type: string
          description: Publisher office id from `POST /offices` or `GET /offices`
          example: off_8k2mQx
        name:
          type: string
          description: Ad name / title
          example: Majorstuenveien 14
        status:
          $ref: '#/components/schemas/AdStatus'
        budget:
          $ref: '#/components/schemas/Budget'
        target_location:
          $ref: '#/components/schemas/TargetLocation'
        start_date:
          type: string
          format: date-time
          description: When the ad may start delivering (inclusive)
          example: '2026-08-20T00:00:00Z'
        end_date:
          type: string
          format: date-time
          description: When the ad must stop delivering (inclusive)
          example: '2026-09-03T23:59:59Z'
        goal_config:
          $ref: '#/components/schemas/GoalConfig'
        publisher_platforms:
          type: array
          description: Platform ids from `GET /publisher-platforms`
          items:
            type: string
          example:
            - drammens_tidende
            - nettavisen
            - romerikes_blad
        material:
          $ref: '#/components/schemas/Material'
        created_at:
          type: string
          format: date-time
          example: '2026-08-19T08:12:00Z'
        updated_at:
          type: string
          format: date-time
          example: '2026-08-19T08:12:00Z'
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: string
          description: Error message
          example: Missing required field
        details:
          type: array
          description: Per-field validation issues
          items:
            type: object
            required:
              - message
            properties:
              path:
                type: array
                items:
                  type: string
                example:
                  - material
                  - target_url
              message:
                type: string
                example: Target URL is required
    Budget:
      type: number
      description: Spend cap for the ad
      example: 5000
    TargetLocation:
      type: object
      required:
        - country
        - lat
        - long
      properties:
        country:
          type: string
          description: ISO 3166-1 alpha-2 country code
          example: 'NO'
        regions:
          type: array
          description: Region or county names
          items:
            type: string
          example:
            - Oslo
        lat:
          type: number
          description: Latitude of the targeting centre
          minimum: -90
          maximum: 90
          example: 59.9294
        long:
          type: number
          description: Longitude of the targeting centre
          minimum: -180
          maximum: 180
          example: 10.7166
        radius_km:
          type: number
          description: Optional radius in kilometres around `lat` and `long`
          example: 10
    GoalConfig:
      type: object
      required:
        - objective
      properties:
        objective:
          type: string
          description: Campaign objective Targeter is optimizing for
          enum:
            - traffic
            - conversions
            - awareness
            - leads
          example: traffic
        optimization_event:
          type: string
          description: Event to optimize delivery against
          enum:
            - impression
            - link_click
            - landing_page_view
            - lead
            - purchase
          example: link_click
    Material:
      type: object
      required:
        - target_url
      properties:
        target_url:
          type: string
          format: uri
          description: Landing page URL for the ad
          example: https://megler.no/eiendom/123
        images:
          type: array
          description: Publicly reachable image URLs
          items:
            type: string
            format: uri
          example:
            - https://example.com/property-photo.jpg
        videos:
          type: array
          description: Publicly reachable video URLs
          items:
            type: string
            format: uri
            example: https://example.com/property-tour.mp4
          example:
            - https://example.com/property-tour.mp4
        html5:
          type: array
          description: Publicly reachable HTML5 creative URLs
          items:
            type: string
            format: uri
            example: https://example.com/creatives/majorstuenveien-14.html
          example:
            - https://example.com/creatives/majorstuenveien-14.html
    AdStatus:
      type: string
      description: Delivery status of the ad
      enum:
        - draft
        - pending_review
        - scheduled
        - active
        - paused
        - completed
        - rejected
        - error
      example: active
  responses:
    BadRequest:
      description: Invalid request payload
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Invalid request payload
            details:
              - path:
                  - name
                message: 'Invalid input: expected string, received undefined'
    Unauthorized:
      description: Missing Authorization header, or invalid or expired token
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            missingHeader:
              value:
                error: Missing or invalid Authorization header
            invalidToken:
              value:
                error: Invalid or expired token
    ServerError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Unexpected server error. Please try again later.
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: >-
        API token issued to Targeter during integration setup. Send as
        `Authorization: Bearer <token>`.

````