Skip to main content
A booking happens when an advertiser’s campaign is approved and takes your schedule and ad units. When you register a campaign booking webhook, Adrop sends an event to your URL each time a booked campaign is approved, changed, paused, resumed, canceled, started, or finished. You can also look up booked campaigns with the API. Events and lookups include the campaign ID and title, status, ad product ID and name, pricing type, budget, advertiser name and URL, schedule, the IDs and names of ad units, apps, targetings, and targeting options, targeting policies, and the Context IDs of options selected in context targeting. They don’t include advertiser contact details such as email, creatives, rates or surcharges, payments, or review details.

Prerequisites

  • You need an API key with these two scopes. The project owner issues keys from [Settings] > [Integrations]. For how to issue a key, see Integrations & API Keys.
  • campaign:subscribe isn’t selected by default when you create an API key, so select it yourself. You can’t change the scopes of a key after it’s issued.
  • Your receiving server needs an https URL that’s reachable from the internet.
Keep the API key on your server only, and never put it in apps or web pages. Events are signed with this key too, so if the key is exposed, revoke it right away and register the webhook again with a new key.

Basic Information


Register a Webhook

Registers the URL that receives events. A project can have one webhook. If one is already registered, this request updates it.

Request

Request Body

  • The existing settings are replaced as a whole. Send all the settings you want, even to change one of them. For example, omitting events switches back to receiving all events.
  • Any other field fails with 400.
  • You can’t register localhost, private or internal addresses, domains that resolve to a private IP, domains that can’t be resolved, or URLs with user information (https://user:pw@host). These fail with 400 WEBHOOK_CONFIG_URL_NOT_ALLOWED.
  • If you register again with another API key, later events are signed with that key. See Key Rotation and Revocation.
  • Campaigns booked before you register don’t get events for that. After you register, use Booked Campaigns once to sync the current state.

Example Request

Example Response

Returns 200 with the saved settings.

Get the Webhook Settings

  • The response has the same format as the response of Register a Webhook.
  • If nothing is registered, it returns 404 WEBHOOK_NOT_FOUND.
  • If active is false, events have stopped because the API key used for registration was revoked. Register again with a new key to resume them.

Delete the Webhook


Receiving Events

When a booked campaign changes, Adrop sends an event to your URL with POST.

Event Types

  • One change sends at most one event. Other values that changed at the same time are in that event’s payload.
  • booking.updated is sent only when a value that you can see actually changes. It’s sent when a targeting option is deleted and the campaign’s targeting conditions change.
  • No event is sent in these cases. The new values appear in the next event and in Booked Campaigns.
    • The name of an ad product, ad unit, app, targeting, or targeting option changes.
    • A creative is approved, rejected, or changed.
    • You create a new targeting option or move a sub-option out of its option group, and booked campaigns automatically get the option’s settings.
  • booking.started and booking.finished can arrive up to an hour after the time passes. Use payload.startTime and payload.endTime for the exact times. Each of the two events is sent only once, within 24 hours after the time passes.

Request Headers

Event Body

Example request
Every event has the same structure. Only eventType and the values at that time differ. The order of keys in an object has no meaning.

Campaign Information

payload and the results of Booked Campaigns have the same structure. A ? at the end of a field name marks an optional field whose key is omitted when it has no value. Each item of units has these fields: Each item of targetings has these fields. Match targetings and targeting options by ID, and use names only for people to read.
  • contexts and contextCount appear only for options that the campaign includes or excludes in context targeting. Audience targetings and options that aren’t selected don’t have them.
  • If a selected option has no Context IDs, contexts is [] and contextCount is 0.
  • To get more than 200 Context IDs, use the Context Targeting API.
Optional fields (title, productTitle, advertiser, title and appTitle in units, title and kind in targetings, and title, contexts, and contextCount in policies) are looked up when the event is sent. If the item was deleted and can’t be found, the key is omitted and only the ID remains, so don’t treat a missing optional field as an error.

Status Values

status is one of the strings below. Compare the strings as they are. status doesn’t depend on whether creatives are approved.

Signature Verification

Every event request has an x-adrop-signature header. Verify the signature before you process the request.
  • signingSecret is the SHA-256 hash, as a hexadecimal string, of the API key used to register the webhook. You compute it from the API key; it isn’t issued separately.
  • t is the signing time in epoch milliseconds. Reject requests where it differs from the current time by more than 5 minutes.
  • Each resend has a new t and signature, but the body, including eventId and timestamp, stays the same.
  • x-adrop-key-id tells you which API key signed the request. While you rotate keys, events signed with either key can arrive.
Verify the signature against the raw bytes of the request body you received. If you turn a parsed JSON object back into a string, the key order or whitespace can change and verification fails.
Node.js (Express) example

Responses and Retries

  • After you process an event, respond with 2xx within 10 seconds. The response body isn’t used. Hand long processing off to run asynchronously, and respond first.
  • For a temporary failure, respond with 5xx. 3xx and 4xx responses aren’t retried.
If you return 401 for a signature error, or a 4xx such as 404 or 429 for a moment during a deployment, that event doesn’t come again. Respond with 5xx for temporary failures.

Event Handling Rules

  1. Filter duplicates by eventId. The same event can arrive up to 5 times. If an eventId you already processed arrives, don’t process it again, and respond with 2xx. Record the eventId only after processing succeeds, so that an event you answered with 5xx after a failed save is processed again when it’s resent.
  2. Don’t rely on arrival order. Resends and simultaneous changes can make events arrive out of order, and the size of eventId doesn’t tell the order either. Keep the last timestamp you applied for each campaign, and ignore only events with a smaller timestamp. Apply events with the same timestamp.
  3. Overwrite with payload. payload is always the full campaign information, so overwriting by campaignId brings you to the latest state even if you miss events or they arrive out of order. If you overwrite with a payload that lacks optional fields, the names you saved before are removed too.
  4. eventType is the change, and status is the state. They don’t always pair up. For example, booking.cancelled for a campaign whose approval was withdrawn before its end has status 심사중, and booking.finished for a campaign that ended while paused has 종료됨.
  5. budget isn’t a settlement amount. For settlement and revenue, use the Report API.

Choosing Events

If you choose events with events and pick only booking.confirmed and booking.cancelled, you miss changes after approval (booking.updated) to the schedule, targeting, ad units, budget, and advertiser information. To reflect changes, also receive booking.updated, or leave events empty to receive all events.

Key Rotation and Revocation

Events are signed with the API key that last registered the webhook. To change keys, follow these steps.
1

Issue a new API key

Issue a new API key with the campaign:read and campaign:subscribe scopes.
2

Deploy verification with both keys

Deploy your receiving server so that it verifies signatures with both the new and the previous key. Tell them apart by x-adrop-key-id.
3

Register again with the new key

Call PUT /webhook with the new key. Events sent after that are signed with the new key.
4

Allow a transition period

Events that were already being sent or waiting for a retry when you registered can arrive signed with the previous key. Wait at least 10 minutes.
5

Revoke the previous key

Revoke the previous key in the console, and remove its verification from your receiving server.
If you revoke the API key used to register the webhook, the webhook is deactivated (active: false) and events stop. When you change keys, always revoke the previous key after you register again with the new key.

Security Recommendations

  • Keep API keys only in a secure place such as a secrets manager, and don’t share them in config files, repositories, or messengers.
  • If a key may have been exposed, revoke it in the console right away. Revocation takes effect immediately, and the webhook registered with that key is deactivated too.
  • Don’t process requests that fail signature verification. Mask the x-adrop-signature value in access logs.

Booked Campaigns

Look up booked campaigns. Use it to sync the current state after you first register the webhook, or to catch up on missed events. It needs the campaign:read scope. The results are approved campaigns whose end time hasn’t passed, either running or not started yet. Each item has the same campaign information structure as the event payload.

List Booked Campaigns

  • Results are sorted by end time (endTime), latest first, then by campaign ID in descending order.
  • If the response has next, there’s another page. Send the next value as is in the next request. The last page has no next.
Example request
Example response
This example reads all booked campaigns from start to finish and saves them.
Full sync example
Campaigns that aren’t in the results have been canceled or have ended. To know whether and when a campaign was canceled, use the booking.cancelled event, not the lookup API.

Get a Booked Campaign

Example request
  • The response has the same structure as one item of items in the list.
  • If campaignId isn’t a ULID, it returns 400.
  • Canceled or finished campaigns, campaigns that aren’t approved, campaigns of other projects, and campaigns that don’t exist all return 404 CAMPAIGN_NOT_FOUND. To know whether a campaign was canceled, use the booking.cancelled event.

Errors

The error code is in the errorCode or message field of the response body.

Integration Checklist

  • You issued an API key with the campaign:read and campaign:subscribe scopes and keep it secure.
  • You registered an https URL with PUT /webhook and confirmed active: true with GET /webhook.
  • You tested signature verification with valid, forged, and expired requests, and you verify against the raw body.
  • You filter duplicates by eventId, and ignore only events with a smaller timestamp than the one you keep.
  • You respond with 2xx within 10 seconds, and with 5xx for temporary failures.
  • You don’t treat missing optional fields as errors, and you treat a contextCount larger than the number of contexts as a partial list.
  • You synced the currently booked campaigns once with GET /campaigns.
  • You have a procedure to verify with both keys during key rotation.

Integrations & API Keys

Issue API keys and set their scopes

Context Targeting API

Manage targeting options and Context IDs from your server