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:subscribeisn’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
httpsURL that’s reachable from the internet.
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
eventsswitches 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 with400 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
Returns200 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
activeisfalse, 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 withPOST.
Event Types
- One change sends at most one event. Other values that changed at the same time are in that event’s
payload. booking.updatedis 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.startedandbooking.finishedcan arrive up to an hour after the time passes. Usepayload.startTimeandpayload.endTimefor 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
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.
contextsandcontextCountappear 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,
contextsis[]andcontextCountis0. - 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 anx-adrop-signature header. Verify the signature before you process the request.
signingSecretis 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.tis 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
tand signature, but the body, includingeventIdandtimestamp, stays the same. x-adrop-key-idtells you which API key signed the request. While you rotate keys, events signed with either key can arrive.
Node.js (Express) example
Responses and Retries
- After you process an event, respond with
2xxwithin 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.3xxand4xxresponses aren’t retried.
Event Handling Rules
- Filter duplicates by
eventId. The same event can arrive up to 5 times. If aneventIdyou already processed arrives, don’t process it again, and respond with2xx. Record theeventIdonly after processing succeeds, so that an event you answered with5xxafter a failed save is processed again when it’s resent. - Don’t rely on arrival order. Resends and simultaneous changes can make events arrive out of order, and the size of
eventIddoesn’t tell the order either. Keep the lasttimestampyou applied for each campaign, and ignore only events with a smallertimestamp. Apply events with the sametimestamp. - Overwrite with
payload.payloadis always the full campaign information, so overwriting bycampaignIdbrings you to the latest state even if you miss events or they arrive out of order. If you overwrite with apayloadthat lacks optional fields, the names you saved before are removed too. eventTypeis the change, andstatusis the state. They don’t always pair up. For example,booking.cancelledfor a campaign whose approval was withdrawn before its end hasstatus심사중, andbooking.finishedfor a campaign that ended while paused has종료됨.budgetisn’t a settlement amount. For settlement and revenue, use the Report API.
Choosing Events
If you choose events withevents 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.
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-signaturevalue 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 thecampaign: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 thenextvalue as is in the next request. The last page has nonext.
Example request
Example response
Full sync example
booking.cancelled event, not the lookup API.
Get a Booked Campaign
Example request
- The response has the same structure as one item of
itemsin the list. - If
campaignIdisn’t a ULID, it returns400. - 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 thebooking.cancelledevent.
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:readandcampaign:subscribescopes and keep it secure. - You registered an
httpsURL withPUT /webhookand confirmedactive: truewithGET /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 smallertimestampthan the one you keep. - You respond with
2xxwithin 10 seconds, and with5xxfor temporary failures. - You don’t treat missing optional fields as errors, and you treat a
contextCountlarger than the number ofcontextsas 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.
Related Documents
Integrations & API Keys
Issue API keys and set their scopes
Context Targeting API
Manage targeting options and Context IDs from your server