Skip to main content
/api/v2/storefront/esa/{esaId}/signals Embedded sales agent (ESA) signal endpoints let a storefront operator manage the signals exposed by a specific ESA adapter. Use these endpoints when the signal is backed by the ESA’s downstream ad server or audience system, such as Google Ad Manager audience segments or custom targeting keys and values. Start every authoring workflow by reading adapter capabilities. Capabilities describe which mapping kinds, candidate types, value types, composition models, and parent-child candidate filters the adapter supports. Do not assume every ESA supports GAM fields.

Endpoints

MethodEndpointDescription
GET/api/v2/storefront/esa/{esaId}/signalsList signals registered on the ESA
GET/api/v2/storefront/esa/{esaId}/signals/{signalId}Read one registered ESA signal
POST/api/v2/storefront/esa/{esaId}/signalsCreate or register a signal on the ESA
POST/api/v2/storefront/esa/{esaId}/signals:validateValidate a signal draft without creating it
GET/api/v2/storefront/esa/{esaId}/signals/adapter-capabilitiesDescribe adapter signal authoring support
GET/api/v2/storefront/esa/{esaId}/signals/candidatesBrowse adapter-backed candidate values

Adapter capabilities

curl https://api.interchange.io/api/v2/storefront/esa/123/signals/adapter-capabilities \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
{
  "data": {
    "adapter": "google_ad_manager",
    "supportsSignalMappingAuthoring": true,
    "mappingKinds": [
      {
        "mappingKind": "audience_segment",
        "label": "Audience segment",
        "candidateType": "audience_segment",
        "supportsSearch": true
      },
      {
        "mappingKind": "gam_targeting_groups",
        "label": "GAM targeting groups",
        "candidateType": null,
        "supportsSearch": false
      }
    ],
    "supportedCandidateTypes": [
      "audience_segment",
      "custom_targeting_key",
      "custom_targeting_value"
    ],
    "candidateTypes": [
      {
        "candidateType": "custom_targeting_key",
        "label": "Custom targeting key",
        "browseOnly": true,
        "childCandidateTypes": ["custom_targeting_value"],
        "supportsSearch": true
      },
      {
        "candidateType": "custom_targeting_value",
        "label": "Custom targeting value",
        "mappingKind": "custom_key_value",
        "directlyMappable": true,
        "parentCandidateType": "custom_targeting_key",
        "supportsParentFilter": true,
        "supportsSearch": true
      }
    ],
    "targetingSemantics": {
      "supportsComposed": true,
      "compositionModels": ["groups"],
      "supportedModes": ["include", "exclude"],
      "mappingKinds": [
        {
          "mappingKind": "gam_targeting_groups",
          "supportsComposed": true,
          "compositionModels": ["groups"],
          "exclusiveWithOtherSignals": true,
          "notes": "Grouped GAM targeting must be used alone for buyer targeting that consumes this field."
        }
      ]
    },
    "valueTypes": ["audience", "binary"]
  }
}

Capability fields

FieldNotes
adapterAdapter implementation behind the ESA, for example google_ad_manager
supportsSignalMappingAuthoringfalse means the ESA can list signals but cannot create drafts from this API
mappingKindsSignal mapping kinds the adapter can create, such as audience_segment, custom_key_value, or gam_targeting_groups
candidateTypesBrowseable adapter objects. Child types can require parent_id when supportsParentFilter is true
targetingSemanticsComposition behavior, include/exclude modes, buyer targeting fields, and warnings such as exclusivity
valueTypesAllowed valueType values for signal drafts

Browse candidates

Candidates are adapter values that can be used to build a signal draft. For parent-child candidate types, first browse the parent and then pass its externalId as parent_id when browsing the child.
curl "https://api.interchange.io/api/v2/storefront/esa/123/signals/candidates?candidate_type=custom_targeting_key&q=DAYOFWEEK&limit=10" \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
curl "https://api.interchange.io/api/v2/storefront/esa/123/signals/candidates?candidate_type=custom_targeting_value&parent_id=17467172&q=FRIDAY&limit=10" \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
{
  "data": {
    "candidates": [
      {
        "candidateType": "custom_targeting_value",
        "externalId": "451422266753",
        "name": "FRIDAY",
        "parentId": "17467172",
        "path": ["DAY OF WEEK", "FRIDAY"],
        "mappingKind": "custom_key_value",
        "defaultSignal": {
          "signalId": "dayofweek_friday",
          "name": "DAY OF WEEK: FRIDAY",
          "valueType": "binary",
          "adapterConfig": {
            "type": "passthrough",
            "kind": "custom_key_value",
            "keyId": "17467172",
            "valueId": "451422266753"
          }
        }
      }
    ],
    "count": 1,
    "nextCursor": null
  }
}

Candidate query parameters

ParameterRequiredNotes
candidate_typeYesCandidate type from candidateTypes[].candidateType
q or queryNoAdapter search string
parent_idNoParent candidate externalId, required by child types that support parent filtering
limitNoPage size
cursorNoCursor returned as nextCursor

Signal draft shape

Creation and validation use the same request body:
FieldTypeRequiredNotes
signalIdstringYesStable caller-supplied signal identifier
namestringYesHuman-readable signal name
descriptionstring or nullNoOperator-facing description
valueTypestringYesOne of the adapter capability valueTypes
tagsstring[]NoOptional labels
adapterConfigobjectYesAdapter mapping configuration

Audience segment

{
  "signalId": "auto_intenders",
  "name": "Auto intenders",
  "valueType": "audience",
  "adapterConfig": {
    "type": "passthrough",
    "kind": "audience_segment",
    "segmentId": "987654321"
  }
}

Direct GAM key-value signal

Use a direct custom_key_value signal when the adapter exposes a specific custom targeting value as directly mappable. Browse values with parent_id so the value remains tied to the correct key.
{
  "signalId": "dayofweek_friday",
  "name": "DAY OF WEEK: FRIDAY",
  "valueType": "binary",
  "adapterConfig": {
    "type": "passthrough",
    "kind": "custom_key_value",
    "keyId": "17467172",
    "valueId": "451422266753"
  }
}

Grouped GAM targeting

Use gam_targeting_groups for composite GAM logic. Groups are OR’d together; criteria inside a group are AND’d together; multiple values inside one criterion are OR’d by GAM for that key. A criterion with exclude: true excludes matching values. Grouped GAM targeting can be exclusive depending on the adapter semantics. If targetingSemantics.mappingKinds[].exclusiveWithOtherSignals is true, do not combine the grouped signal with another signal targeting the same buyer field.
{
  "signalId": "weekday_or_sports",
  "name": "Weekday or sports package",
  "valueType": "binary",
  "adapterConfig": {
    "type": "passthrough",
    "kind": "gam_targeting_groups",
    "groups": [
      {
        "criteria": [
          {
            "keyId": "17467172",
            "values": ["451422266753", "451420638792"]
          },
          {
            "keyId": "98765",
            "values": ["12345"],
            "exclude": true
          }
        ]
      },
      {
        "criteria": [
          {
            "keyId": "24680",
            "values": ["13579"]
          }
        ]
      }
    ]
  }
}

Validate a draft

curl -X POST https://api.interchange.io/api/v2/storefront/esa/123/signals:validate \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "signalId": "weekday_or_sports",
    "name": "Weekday or sports package",
    "valueType": "binary",
    "adapterConfig": {
      "type": "passthrough",
      "kind": "gam_targeting_groups",
      "groups": [
        {
          "criteria": [
            {
              "keyId": "17467172",
              "values": ["451422266753"]
            }
          ]
        }
      ]
    }
  }'
{
  "data": {
    "valid": true,
    "issues": []
  }
}
Validation does not persist the signal. Use it before create when a client is assembling adapterConfig manually.

Create a signal

curl -X POST https://api.interchange.io/api/v2/storefront/esa/123/signals \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "signalId": "dayofweek_friday",
    "name": "DAY OF WEEK: FRIDAY",
    "valueType": "binary",
    "adapterConfig": {
      "type": "passthrough",
      "kind": "custom_key_value",
      "keyId": "17467172",
      "valueId": "451422266753"
    }
  }'
{
  "data": {
    "signalId": "dayofweek_friday",
    "name": "DAY OF WEEK: FRIDAY",
    "valueType": "binary",
    "adapterConfig": {
      "type": "passthrough",
      "kind": "custom_key_value",
      "keyId": "17467172",
      "valueId": "451422266753"
    }
  }
}

List and get signals

curl https://api.interchange.io/api/v2/storefront/esa/123/signals \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
curl https://api.interchange.io/api/v2/storefront/esa/123/signals/dayofweek_friday \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
Signal response objects include at least signalId and name; adapters can return additional fields such as description, status, valueType, adapterConfig, coverageForecast, createdAt, and updatedAt.

Errors

  • 400 VALIDATION_ERROR — invalid ESA id, malformed draft, missing required fields, or an adapter validation issue.
  • 401 UNAUTHORIZED — missing or invalid bearer token.
  • 404 NOT_FOUND — ESA or signal does not exist for the caller.
  • 502 or 503 — the ESA adapter or tenant-management service could not complete the request.
See Errors for the full error contract.

Storefront signal tasks

Storefront-owned signal CRUD and discovery

Signal overview

Signal model and lifecycle

Storefront API reference

OpenAPI reference for storefront routes