> ## Documentation Index
> Fetch the complete documentation index at: https://docs.interchange.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Signal

> Audience and contextual segments registered, discovered, and deployed to DSPs

## Overview

A **Signal** is a named segment used for targeting — an audience, contextual cohort, or first-party data slice. Signals are registered with Scope3 (or auto-discovered from external signals agents like LiveRamp), exposed via the v2 REST API, and deployed to DSPs/SSPs for use in media buys.

The v2 signal model is conceptually identical to v1 — the same registration, discovery, access tier, and deployment semantics apply — but is now exposed via stable v2 REST endpoints under `/api/v2/storefront/signals`.

<Note>
  **Storefront-mounted**: Signal management endpoints live on the storefront router (`/api/v2/storefront/signals/...`) even though buyers and advertiser operators interact with the resulting signals on campaigns. This is because signals are owned by the agent/advertiser (storefront context) and surfaced to buyers via discovery and campaign attachment.
</Note>

## Signal sources

<CardGroup cols={2}>
  <Card title="First-party (custom)" icon="upload">
    Audiences you upload — CRM segments, behavioral cohorts, geographic territories. No additional cost.
  </Card>

  <Card title="Agent-managed" icon="robot">
    Surfaced by external signals agents (LiveRamp, Optable, custom) using the ADCP signals protocol. Agents own the segments they create.
  </Card>

  <Card title="Third-party" icon="database">
    External data providers (weather, behavioral, contextual). Premium signals incur additional CPM cost.
  </Card>

  <Card title="Built-in" icon="sparkles">
    Scope3-provided quality and viewability signals always available — no setup required.
  </Card>
</CardGroup>

## Key fields

| Field         | Type      | Notes                                                                                                                                                                               |
| ------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `signalId`    | string    | Stable signal identifier. **You author it** — the platform does not assign one                                                                                                      |
| `name`        | string    | Human-readable name                                                                                                                                                                 |
| `description` | string    | What the segment represents                                                                                                                                                         |
| `keyType`     | string\[] | The identifiers the segment is keyed on. At least one required, and **immutable** after registration. See [Key types and the privacy boundary](#key-types-and-the-privacy-boundary) |
| `regions`     | string\[] | Where the signal is available: `NORAM`, `LATAM`, `EMEA`, `APAC`, `ANZ`, `GLOBAL`. **Immutable** after registration                                                                  |
| `isLive`      | boolean   | Deployed and accepting buys                                                                                                                                                         |
| `agentId`     | string    | Owning signals agent, on registration, for agent-managed signals                                                                                                                    |
| `access`      | object\[] | Who may use the signal, and at what price — see [Access records](#access-records). Visibility and pricing live here, not on the signal                                              |

Only `name`, `description`, `isLive` and the access records can change after
registration. `keyType`, `regions` and `metadata` are fixed — register a
replacement signal if the shape itself is wrong.

## Key types and the privacy boundary

`keyType` declares what the segment is keyed on, and every value belongs to
exactly one of two classes:

| Class        | What it describes                  | Values                                                                                                                      |
| ------------ | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| **Context**  | The impression — where the ad runs | `country`, `region`, `metro`, `topic`, `eidr`, `gracenote`, `isrc`, `gtin`, `rss_guid`, `isbn`, `url`, `url_hash`, `custom` |
| **Identity** | The person                         | `maid`, `rampid`, `rampid_derived`, `hashed_email`, `hashed_phone`, `id5`, `uid2`, `euid`, `pairid`                         |

<Warning>
  **A single signal cannot mix the two classes.** Registering one with both a
  context and an identity key type is rejected: combining them would let the
  reader correlate a person with the content they saw, which the AdCP
  context/identity separation exists to prevent. Register two signals instead.
</Warning>

Use `custom` only when no structured type fits — it is the AdCP escape hatch,
where publisher and buyer agree out of band what the values mean.

## Lifecycle

<Steps>
  <Step title="Register or discover">
    Register first-party signals via `POST /api/v2/storefront/signals`. Discover external signals via `POST /api/v2/storefront/signals/discover` against signals agents.
  </Step>

  <Step title="Deploy">
    Deploy signals to DSPs/SSPs so they become addressable in media buys. Agent-managed signals deploy through the agent.
  </Step>

  <Step title="Activate in campaigns">
    Reference the signal as a target audience on a campaign (`audienceConfig.targetAudienceIds`) or in a brand story.
  </Step>

  <Step title="Monitor / archive">
    Track signal effectiveness through campaign reporting. Archive with `DELETE /api/v2/storefront/signals/:signalId`.
  </Step>
</Steps>

<Warning>
  **Archiving cascades into targeting.** `DELETE` archives the signal, all of its
  access records, **and every custom-signals targeting profile that references
  it** — in either its include or its exclude set. Any buyer targeting built on
  this signal stops working. Archiving is also one-way here: a repeat call reports
  the signal as already archived rather than restoring it. Confirm nothing live
  depends on the signal before you archive it.
</Warning>

## Common operations

### Register a first-party signal

```bash theme={null}
curl -X POST https://api.interchange.io/api/v2/storefront/signals \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "signalId": "high_value_customers",
    "name": "High value customers",
    "description": "Top 10% LTV customers — refreshed weekly",
    "keyType": ["hashed_email"],
    "regions": ["NORAM"],
    "access": [
      { "advertiserId": 88421, "visibility": "PROPRIETARY" }
    ]
  }'
```

### Discover signals from an agent

```bash theme={null}
curl -X POST https://api.interchange.io/api/v2/storefront/signals/discover \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agentId": "liveramp_signals_agent",
    "signalSpec": "premium auto intenders, last 30 days"
  }'
```

Discovery reads the connected agents' catalogs live and **persists nothing** —
it returns what is on offer. Registering something it found is a separate
`POST /signals` call. It only returns results for signals agents already
connected to your account, so an empty response means "no connected agent
matched", not "no such segment exists".

The discover endpoint queries the agent's catalog (RAG-style) and returns the most relevant segments along with metadata.

### List / get / update / delete

```bash theme={null}
# List with filters
curl "https://api.interchange.io/api/v2/storefront/signals?agentId=liveramp_signals_agent&visibility=PROPRIETARY&isLive=true&limit=100" \
  -H "Authorization: Bearer $SCOPE3_API_KEY"

# Filter to a specific advertiser
curl "https://api.interchange.io/api/v2/storefront/signals?advertiserId=88421" \
  -H "Authorization: Bearer $SCOPE3_API_KEY"

# Get one
curl https://api.interchange.io/api/v2/storefront/signals/sig_abcd \
  -H "Authorization: Bearer $SCOPE3_API_KEY"

# Update
curl -X PUT https://api.interchange.io/api/v2/storefront/signals/sig_abcd \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "description": "Refined definition — top 5% LTV" }'

# Archive
curl -X DELETE https://api.interchange.io/api/v2/storefront/signals/sig_abcd \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
```

## Access records

Visibility and price are **not fields on the signal**. They live on `access`
records, one per advertiser the signal is offered to, so the same signal can be
public to one buyer and priced for another.

| Field          | Type   | Notes                                              |
| -------------- | ------ | -------------------------------------------------- |
| `advertiserId` | int64  | The Scope3 advertiser this record grants access to |
| `visibility`   | enum   | `PUBLIC` or `PROPRIETARY`                          |
| `price`        | object | Optional per-advertiser pricing option             |

| Visibility    | Description                                  |
| ------------- | -------------------------------------------- |
| `PUBLIC`      | Discoverable platform-wide                   |
| `PROPRIETARY` | Scoped to the advertiser named on the record |

Update access with `addAccess`, `updateAccess` (by `accessId`) and
`archiveAccess` on `PUT /signals/:signalId`. Archiving the signal archives every
one of its access records too.

Partner agents can list and manage signals across multiple advertisers they have access to. The `advertiserId` filter on list lets a partner narrow to one client at a time.

## Signal RAG and optimization

When a campaign runs, Scope3's RL optimizer uses signals as inputs alongside built-in quality and viewability data:

1. **Collect** — gather available signals on each impression opportunity (custom, third-party, agent-managed, built-in)
2. **Retrieve** — pull signals relevant to the campaign's brief and optimization goals
3. **Optimize** — bias bidding and budget allocation toward signal combinations that perform well
4. **Learn** — feed measured outcomes back to inform future signal usage

This is the model AdCP and Scope3 refer to as **Signal RAG**. The platform documents which signals drove decisions so you can trace optimization choices.

## Deployment

Some signals require deployment to a DSP before they're addressable:

* **First-party**: deployed by Scope3 to integrated DSPs after registration
* **Agent-managed**: deployed by the agent (e.g. LiveRamp deploys RampIDs to its connected DSPs)
* **Built-in**: always available, no deployment needed

`isLive: true` in the response confirms the signal is deployed and bidding is possible.

## Pricing

| Source        | CPM premium                              |
| ------------- | ---------------------------------------- |
| First-party   | None                                     |
| Agent-managed | Per-agent (LiveRamp, Optable, etc.)      |
| Third-party   | Per-provider; surfaced in pricing fields |
| Built-in      | None                                     |

Premium signal cost is added on top of the publisher's CPM at the media buy level and is paid out of the media portion of your gross budget — see the media buy's `budget_breakdown` and [Budgets and fees](/v2/concepts/budgets-and-fees) for how the media/fee split is reported.

## Related concepts

<CardGroup cols={2}>
  <Card title="Campaign" href="./campaign" icon="rocket">
    Reference signals as `audienceConfig.targetAudienceIds`
  </Card>

  <Card title="Brand" href="./brand-story" icon="book-open">
    Brand identity that contextualizes signal usage
  </Card>

  <Card title="Discovery" href="../guides/discovery" icon="magnifying-glass">
    Discovery uses signals to refine product matches
  </Card>

  <Card title="Storefronts" href="/v2/object-guides/storefront" icon="store">
    Browse storefronts and register credentials per inventory source
  </Card>
</CardGroup>
