Skip to content
Deliver to a Partner Endpoint
.md

Deliver to a Partner Endpoint

Activate an Audience covers the shape of an activation. This guide is the per-partner version of that journey: taking one completed audience and landing it at one specific destination, with the exact ids, streams and account details that destination expects.

The pattern is always the same, whichever partner you deliver to. You read the connection, read what its partner offers, fill in that partner’s inputs, and send one activation. Nothing about the partner is guessed or typed from memory.

This page never lists partners, their pricing models, their datastreams, or their input fields. That catalog is specific to your account and changes over time, so the reference reads below are the only accurate source. Code that hardcodes a partner name, a pricing model id, or an input order breaks the first time the catalog changes.

Before you start

  • A bearer token (Authentication).
  • An audience in status 104 Completed that passes every activation eligibility gate (device-count floor, Affinity SCID coverage, retention - see the gate table in Read an Audience). The audience read returns an explicit is_activation_allowed boolean and, when it is false, eligibility.reasons[] explains which gate blocked it - check it before you build the request.
  • An endpoint connection for the destination you want.
Endpoint connections are created in the console, under Audience Manager - not through the API. The API reads the connections that already exist for your account and activates into them. If the destination you need is not in the list, or you want a new partner enabled, your Account Manager sets it up; some destinations require additional permissions which need to be approved by your Account Manager.

Step 1 - Find the endpoint connection

Everything else in this journey hangs off the connection. It is the anchor of the activation: the platform resolves the partner, the pricing options and the datastreams from it, server-side.

curl "https://console.intuizi.com/api/v2/analyses/reference/common/endpoint-connections" \
  -H "Authorization: Bearer <YOUR_TOKEN>" \
  -H "Accept: application/json"

Each entry carries the connection id, its name, and the partner behind it - including that partner’s input definitions:

{
  "id": 12,
  "name": "Acme Production",
  "partner": {
    "id": 3,
    "name": "Acme DSP",
    "inputs": [
      { "name": "Account ID", "type": "text", "required": true, "description": "Partner account id", "placeholder": "Account ID", "default_value": null },
      { "name": "Account Credentials", "type": "file", "required": true, "description": "Service Account .json file", "placeholder": "Service Account .json file", "default_value": null }
    ]
  }
}

Keep three things from this response: the connection id (for endpoint_connection_id), the partner.id (the next two reads need it), and the partner.inputs array in the order it arrives - that order is the contract for Step 4.

Use search to narrow a long list by connection name. The full field contract is in Get Endpoint Connections; the read never returns stored credentials or stored input values.

Step 2 - Read that partner’s pricing models

Pricing is per partner, so this read takes the partner_id you just kept:

curl "https://console.intuizi.com/api/v2/analyses/reference/common/pricing-models?partner_id=3" \
  -H "Authorization: Bearer <YOUR_TOKEN>" \
  -H "Accept: application/json"
{ "data": [ { "id": 9, "name": "CPM", "price": "2.50" } ] }

Pick one id - that is your pricing_model_id. See Get Pricing Models.

You supply the pricing model id, never a pricing model name. The activation request prohibits partner_id, partner_name and pricing_model; sending any of them returns 422. Identity always comes from the connection.

Step 3 - Read that partner’s datastreams

Datastreams are the outputs the partner exposes. Same partner_id:

curl "https://console.intuizi.com/api/v2/analyses/reference/common/datastreams?partner_id=3" \
  -H "Authorization: Bearer <YOUR_TOKEN>" \
  -H "Accept: application/json"
{ "data": [ { "id": 7, "name": "Match File" } ] }

Keep the id of every stream you want delivered. See Get Datastreams.

A stream is only delivered when you enable it explicitly:

"datastreams": [ { "id": 7, "status": true } ]

An entry without "status": true is not activated, so an activation whose streams are all left disabled has nothing to deliver.

Step 4 - Map the partner’s account inputs

Most partners need account details alongside the audience - an account id, a seat id, a folder prefix, a service-account key. Those are the partner.inputs definitions from Step 1. Each definition carries a name, a type (text or file), a required flag and UI hints, and the array order is meaningful.

You send values, not names, and they are matched to the definitions by index:

  • audience_inputs - one array for the whole activation.
  • datastreams[].inputs - one array per stream, for streams that need different values. A per-stream value wins over the top-level one at the same index.
  • A text definition flagged required must resolve to a value for every enabled datastream, from the per-stream array, the top-level array, or the definition’s default_value. One left empty is rejected with a 422 naming that input. A default_value passes this check but is not copied into the delivery, so send the value explicitly. A file definition travels separately (below).

For the example connection in Step 1, the mapping is:

IndexnametyperequiredWhere its value goes
0Account IDtextYesaudience_inputs[0] or datastreams[].inputs[0]
1Account CredentialsfileYesdatastreams[].service_account

Read your own connection’s definitions the same way: walk the array, note the index of each one, and place your values at those indexes. Keep positions aligned by sending null at an index whose value travels elsewhere (a file input, below) rather than shortening the array.

Service-account keys

A file-type definition is the destination’s service-account JSON key (GCP-style destinations). It does not travel in the input arrays. Send the decoded JSON object as datastreams[].service_account on each enabled stream. It is accepted only for partners that define a file input - sending it to a partner that does not is rejected with 422.

Step 5 - Decide how the delivery authenticates

By default the delivery authenticates with the stored credentials on the endpoint connection, and you send no credentials at all. Supply the credentials object only when you hold the destination credentials yourself: caller-supplied credentials override the stored ones for that one delivery, and if neither exists the activation is rejected with 422.

Credentials are secret material. Send them only over HTTPS, never log them on your side, and never put them in a URL or query string. They are accepted in the request body, used to authenticate the delivery, and never returned by the API. See Endpoint Connections & Partners.

Step 6 - Send the activation

POST /api/v2/analyses/activations/create

One request carries the audience, the connection, the pricing model, the enabled streams and the partner inputs.

curl -X POST "https://console.intuizi.com/api/v2/analyses/activations/create" \
  -H "Authorization: Bearer <YOUR_TOKEN>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Idempotency-Key: <UNIQUE_KEY>" \
  -d '{
    "audience_id": 88,
    "endpoint_connection_id": 12,
    "pricing_model_id": 9,
    "description": "Q1 retail delivery",
    "audience_inputs": ["ACME-4471", null],
    "datastreams": [
      {
        "id": 7,
        "status": true,
        "service_account": { "type": "service_account", "project_id": "acme-delivery" }
      }
    ]
  }'

The response returns the new activation with its id and an opening lifecycle status. Field by field, the body contract is in API Reference - Activations, including the optional delivery tuning fields (limit, compression, frequency and distance caps, project_id, notification).

Idempotency-Key is optional and you generate it yourself - one unique string per logical delivery. Resend the same key only when retrying that exact request: the retry replays the original response instead of launching a second delivery. See Idempotency.

Step 7 - Poll the delivery

Delivery is asynchronous (see The Async Model). Poll the activation until its lifecycle status reaches 104 Completed:

curl "https://console.intuizi.com/api/v2/analyses/activations/501" \
  -H "Authorization: Bearer <YOUR_TOKEN>" \
  -H "Accept: application/json"
  • 100-103, 108, 109 - still processing. Poll again shortly.
  • 105 DataStreaming - the delivery to the destination is in flight. 105 happens before 104, so keep polling.
  • 104 Completed - the only terminal success state.
  • 107 Additional Info - the export stopped and will not continue. Stop polling. Audience Manager shows the reason on the activation.
  • 4xx lifecycle ids - an error state. Stop polling and inspect the resource.

Each entry in the datastreams array of the read reports that stream’s name, its status, a results object (carrying a uri when an output file is available) and an error string only when that stream failed - so a partial delivery is visible per stream, not just per activation. Data delivered into the destination configured on the connection lands there directly; the API does not proxy it. See Read an Activation for the full response, and Polling and Rate Limits for sensible intervals.

Delivering again

Activations are point-in-time. To deliver a refreshed audience, build the new audience and create a new activation against the same connection with a new Idempotency-Key; to deliver the same audience to a second destination, repeat Steps 1-6 with that destination’s connection id and its own partner inputs.

An activation is a live, billable, non-reversible delivery to an external destination. Activate only completed audiences, against the connection you intend, with the pricing model you intend.

Checklist

  • Connection id read from endpoint-connections, not hardcoded.
  • pricing_model_id and every datastream id read for that connection’s partner.id.
  • Each stream you want delivered carries "status": true.
  • Every required input definition resolves to a value for every enabled stream, index-matched to partner.inputs.
  • service_account sent only when the partner defines a file input.
  • Credentials either stored on the connection or supplied in the body.
  • No partner_id, partner_name or pricing_model in the request.

Rejection shapes and status codes are documented once, on Errors.

Reference