Skip to main content
A seller account connects its ad server as an inventory source through V3. The supported ad servers are Google Ad Manager, FreeWheel, SpringServe, AdsWizz, Broadsign and Epsilon Retail Media (CitrusAd). What Broadsign asks for and does is described below. For the others, what each one asks for and what Apostra does with that access is described in Ad server access.

Start from an agent

An agent starts a connection with save_inventory_source and only adServer:
type is google_ad_manager, freewheel, springserve, adswizz, broadsign or citrusad. The call creates nothing. It returns action: "ad_server_form" and opens the Connect ad server form, where the seller enters the ad server’s details and credentials. Credentials are never passed in an agent’s tool call, so they never pass through chat. Sending adServer with any other field is refused with VALIDATION_FAILED. For Google Ad Manager the result also carries serviceAccountEmail. Apostra signs in to GAM with a service account it creates for your organization, and you add that email as a user in your GAM network before connecting. The first call creates the service account; later calls return the same one. An agent can tell the seller which email to add without opening the form. open_page({ "page": "connect_ad_server" }) opens the same form without choosing an ad server first.

What the form does

The form sends the ad server’s configuration and credentials to Apostra, which forwards the credentials to the managed source and never stores them on the Apostra connection or returns them. On an existing source, the ad-server source page sends the replacement configuration the same way. Google Ad Manager’s network settings are replaced in place. For the other ad servers the credentials are rotated in place, so the source keeps its products and sync history. Epsilon Retail Media connects in two steps: the form creates the source, then stores its API key. If storing the key fails, the form retries against the source it already created instead of creating a second one. These form writes are page-only. They are not part of an agent’s tool list, the public V3 HTTP API or the SDKs.

Broadsign

Broadsign sells digital out-of-home screen time. Apostra connects to Broadsign Guaranteed Campaigns (Broadsign Direct), the system that books screen time. What you provide.
  • A production Broadsign Guaranteed Campaigns login email and password. The user must be active and allowed to read screens and to create and book proposals.
  • The three-letter currency your Broadsign domain prices in.
Broadsign does not report a currency through its API, so the currency you enter is the currency every booking uses. It must match your storefront’s settlement currency before a booking can become ready. What Apostra keeps. Every Broadsign connection pins the broadsign:v1 connection contract, which fixes the production Direct API and an email and password login. The password is forwarded to the managed source and never stored on or returned by the Apostra connection. Only the email, the production environment, the domain currency and the contract stay on the connection. What the connection does.
  • Reads your domain’s screens.
  • Books one Broadsign proposal per media buy, with one line item per package.
  • Reads each buy’s status and its flight-to-date delivery: delivered impressions from the line items, and spend as those impressions at the booked CPM.
  • Sends flight date changes to Broadsign as amendments.
  • Cancels.
Budget and impression changes are refused. Pausing, creative trafficking, and daily plays and proof-of-play need Broadsign Control, a separate Broadsign API that this connection does not include. You schedule creative in Broadsign yourself. If Broadsign rejects the login, the connection reports ADAPTER_INVALID_CREDENTIALS or ADAPTER_PERMISSION_DENIED. Check the email and password and the user’s permissions, then save them again on the ad-server source page.

After connecting

The new source appears in search({ "kind": "inventory_source" }). Read its connection state and setup progress with get({ "kind": "inventory_source", "id": "SOURCE_ID" }). See Reading an inventory source for what that read returns.