# Creating Product-Based Ads with Kevel's API

With a product catalog synced to Kevel, it is possible to create product-based ads (PLAs and other formats) via API or UI. This page describes the process using Kevel's API. There are two ways to create product ads via API:

1. A fixed list of SKUs
2. A query specifying product characteristics

Product ads can be created at the same time as the Campaign and Flight(s) they belong to using the [Create Campaign v2](https://dev.kevel.com/reference/create-campaign-v2) endpoint (recommended) or separately associated with existing Flights using Kevel's _Jobs_ API, an asynchronous service that handles longer-running batch operations in the system. In both cases, Kevel facilitates the creation of many product ads in a single request and returns a Job ID. The Job ID is used to poll for the status of the Job and when complete a list of Ad IDs is returned. See the [Submit Job API documentation](https://dev.kevel.com/reference/submit-jobs) for more details.

Aside from the difference in how the products are specified, there are other key differences between the options:

1. Option #1 supports providing _overrides_ alongside the list of SKUs allowing you to set product bids, for example, and other Ad-level settings on a per-product basis. This is not supported with Option #2.
2. Option #1 allows you to manually inactivate and activate products via the UI/API. This is not allowed for Option #2, where the Ads are fully managed by the Kevel system.

## Create a Campaign with Product Ads

Below is a complete example request to create a Campaign with one Flight filled with product ads for the brand `cashewco`. See additional sections that follow for more examples and definitions of all fields included in the `Jobs` object for use within `Flights` or in standalone calls to the Jobs API.

### cURL Example

```curl
curl --request POST \
     --url https://api.kevel.co/v2/campaign \
     --header 'X-Kevel-ApiKey: XXX' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '\
{\
  "AdvertiserId": 11111,\
  "Name": "Product Query Example Campaign",\
  "IsActive": true,\
  "Flights": [\
    {\
      "Name": "Product Ad Flight 1",\
      "StartDateISO": "2025-02-06T00:00:00.000Z",\
      "PriorityId": 22222,\
      "GoalType": 8,\
      "Impressions": 1002,\
      "IsActive": true,\
      "RateType": 3,\
      "EndDateISO": "2025-02-28T00:00:00.000Z",\
      "Price": 2,\
      "Keywords": "",\
      "TimeZone": "UTC",\
      "Jobs": [\
        {\
          "TaskId": "create-ads-from-product-query",\
          "TaskArgs": {\
            "AdTemplateUri": "itemdb://12345/101/0e9321b3-1446-47ec-b1d7-705bfb7b3fb5",\
            "ProductQuery": [["brandId","cashewco"]]  
          }\
        }\
      ]\
    }\
  ]\
}  
'
```

## Product Ad Creation Details

### Using a Query

Use the `create-ads-from-product-query` taskId and a `ProductQuery`. Here's an example:

### cURL Example

```curl
curl --request POST \
     --url https://api.kevel.co/v1/job/ \
     --header 'X-Kevel-ApiKey: XXX' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '\
{\
  "TaskId": "create-ads-from-product-query",\
  "TaskArgs": {\
    "FlightId": 456789,\
    "AdTemplateUri": "itemdb://12345/101/0e9321b3-1446-47ec-b1d7-705bfb7b3fb5",\
    "ProductQuery": [\
      [["one-of", "kevel/brand-id"], [12345, 12346]],\
      ["kevel/merchant-id", 12347]  
    ]\
  }\
}  
'
```

### Ad Template URI

In most cases, the Ad Template URI will be constant for all create ads from products requests unless a customer is using multiple ad templates (e.g., for different PLA formats or placements).

- **Example URI:** `itemdb://12345/101/0e9321b3-1446-47ec-b1d7-705bfb7b3fb5`  
- **Structure:** `itemdb://{network_id}/{ad_templates_table_id}/{template_uuid}`

### Product Query

The `ProductQuery` array contains a list of 2-item arrays (called "clauses"), each describing a match criterion. The first item of each clause is an array of the `op` and the `field`. The second item of each clause is the value that should be matched.

Supported `op` values are `=`, `<`, `>`, `<=`, `>=`, `not=`, `one-of`, `present?`, `matches`, and `matches-phrase`.

### Changing Product Queries

The `create-ads-from-product-query` task can be called multiple times with the same Flight ID, and each call results in an update of the Ads in the Flight.

### Example for a Fixed List of SKUs

Use the `create-ads-from-products` taskId, a list of ItemDB product URIs, and optionally a set of overrides.

### cURL Example

```curl
curl --request POST \
     --url https://api.kevel.co/v1/job/ \
     --header 'X-Kevel-ApiKey: XXX' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '\
{\
  "TaskId": "create-ads-from-products",\
  "TaskArgs": {\
    "FlightId": 456789,\
    "AdTemplateUri": "itemdb://12345/101/0e9321b3-1446-47ec-b1d7-705bfb7b3fb5",\
    "ProductUris": [\
      "itemdb://12345/100/01936422964",\
      "itemdb://12345/100/01936422955"\
    ],\
    "Overrides": {\
      "itemdb://12345/100/01936422964": [\
        {\
          "target": [\
            "ad",\
            "price"\
          ],\
          "source": "5",\
          "op": "constant"\
        }\
      ],\
      "itemdb://12345/100/01936422955": [\
        {\
          "target": [\
            "ad",\
            "price"\
          ],\
          "source": "3.5",\
          "op": "constant"\
        }\
      ]\
    }\
  }\
}  
'
```

### Native Product Ads

A Native Product Ad (NPA) is a type of ad that allows you to link a single Ad to multiple Products. In most respects, it behaves like a Product Listing Ad (PLA), but with one important difference: instead of creating one Ad per Product, the system will generate a single Ad that aggregates data from all specified Products.

### Example to Create a Native Product Ad via the Jobs API

```curl
curl --request POST \
     --url https://api.kevel.co/v1/job/ \
     --header 'X-Kevel-ApiKey: XXX' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '\
{\
  "TaskId": "create-native-product-ad",\
  "TaskArgs": {\
    "FlightId": 456789,\
    "AdTemplateUri": "itemdb://12345/101/f3406d28-7cc9-41e2-abb1-a46b750d3861",\
    "ProductUris": [\
      "itemdb://12345/100/01936422964",\
      "itemdb://12345/100/01936422955"\
    ],\
    "Overrides": {\
      "global": [\
        {\
          "source": "My Native Product Ad",\
          "target": ["creative", "Title"],\
          "op": "constant"\
        },\
        {\
          "source": "https://mycdn.com/productcollage.jpg",\
          "target": ["creative", "TemplateValues", "ctmain_image"],\
          "op": "constant"\
        }\
      ]\
    }\
  }\
}  
'
```

Note: the `Overrides` structure matches Overrides for the `create-ads-from-products`, but only a single key `"global"` is supported, as opposed to unlimited product-uris.
