RDN Data Ingestion API
Simple, authenticated REST API for retailers to send transaction data to the Adperical Retail Data Network.
Overview
The RDN Ingestion API allows retailers to send point-of-sale transaction data securely to Adperical. This data powers audiences and closed-loop measurement for brand campaigns.
The API is designed to be simple:
- Single endpoint for all transaction data
- API key authentication (no OAuth complexity)
- JSON request/response format
- Accepts single transactions or batches
- All PII is hashed on ingestion — no raw customer data is stored
Authentication
All requests must include your API key in the X-API-Key header.
Your API key is provided when your retailer account is created. It can be found in the Data Config section of your RDN portal.
Base URL
Error Handling
All errors return JSON with an error field:
| Status | Meaning |
|---|---|
| 200 | Success |
| 400 | Bad request — check your payload |
| 401 | Missing or invalid API key |
| 403 | Account not active |
| 500 | Server error — retry or contact support |
Ingest Transactions
POST /api/rdn/ingest
Send one or more transactions. Each transaction represents a single purchase event at a store.
Single Transaction
Batch Ingest
Send multiple transactions in one request using the transactions array:
Response
Transaction Object
| Field | Type | Required | Description |
|---|---|---|---|
| store_id | string | recommended | Unique identifier for the store location (e.g. "tawfeer-jnah") |
| timestamp | ISO 8601 | recommended | Transaction date/time. Defaults to current time if omitted. |
| total | number | recommended | Total transaction amount |
| customer_id | string | optional | Customer identifier (phone, email, loyalty ID). Hashed on ingestion — never stored raw. |
| items | array | required | Array of item objects (see below) |
Item Object
| Field | Type | Required | Description |
|---|---|---|---|
| sku | string | optional | Product SKU or barcode |
| category | string | recommended | Product category (e.g. "Dairy", "Sauces", "Beverages") |
| brand | string | recommended | Product brand (e.g. "Toom Time", "Taanayel") |
| qty | integer | optional | Quantity purchased. Defaults to 1. |
| amount | number | recommended | Line item total amount |
customer_id field is SHA-256 hashed immediately on ingestion. The raw value is never stored, logged, or accessible. You can send phone numbers, emails, or loyalty IDs — all are hashed identically.CSV Upload
If API integration isn't feasible, you can upload CSV files directly through the RDN Retailer Portal.
Expected CSV format:
Each row represents one item. Rows with the same timestamp + customer_id (or same total) are grouped as a single transaction.
Example: cURL
Example: JavaScript
Example: Python
Partner & Agent Access (MCP / AdCP)
Beyond ingestion, the network exposes its audiences, in-store inventory and measurement to approved buyers — universal buying platforms, agencies, advertisers, and the agents that run on them — through a Model Context Protocol (MCP) server. The server is an AdCP 3.2 Signals agent: get_adcp_capabilities, get_signals and activate_signal follow the published Ad Context Protocol 3.2 schemas, and the network's standing signal catalog is published at /.well-known/adagents.json (data provider domain adperical.com). In-store media, measurement and activation status are network-native tools prefixed rdn_; they make no AdCP Media Buy conformance claim. Access is per partner, under the network's neutrality rules. Status: preview, by approval.
Endpoint and authentication
The server speaks JSON-RPC 2.0 over POST (single requests or batches) and answers with JSON; it does not open a server-sent event stream. Point any MCP client at the URL with the header above, or call it directly. Partner keys are issued by the operator and shown once; only a hash is stored. Every tool is scoped to retailers that have opted in to partner distribution, intersected with the retailers your partner may see, and to segments those retailers have opted in. A retailer that has not opted in is invisible to every partner. Anonymous discovery is not offered.
Tools
| Tool | AdCP | What it does |
|---|---|---|
get_adcp_capabilities | Core | Protocol versions and features: AdCP 3.2, supported_protocols: ["signals"], discovery modes brief and wholesale, idempotency with 24-hour replay. |
get_signals | Signals | Match a natural-language signal_spec (or exact signal_refs) to purchase-based segments. Each listing carries signal_agent_segment_id, signal_ref, signal_type: "owned", the data provider, pricing_options (CPM data fee) and a deployments entry per requested destination. discovery_mode: "wholesale" enumerates the full priced feed with cursor pagination. |
activate_signal | Signals | Request deployment to one or more destinations: {type:"platform", platform} for meta, google, the-trade-desk or retailer-media, or {type:"agent", agent_url}. Requires a UUID idempotency_key. The operator approves and exports the hashed audience; once live, the deployment carries the activation_key. action: "deactivate" withdraws it. |
rdn_get_activation_status | native | Status of an activation and the decisioning-platform segment id once live. |
rdn_list_retailers | native | Retailers in your scope and what each offers (audiences, media products). |
rdn_get_products | native, preview | Bookable in-store surfaces (screens, shelf, end-caps, receipts, loyalty, sampling) with formats, pricing, availability and the measurement attached. |
rdn_create_media_buy | native, preview | Book products for a flight, optionally targeted with signals. Returns a media_buy_id pending operator acceptance. |
rdn_get_media_buy_delivery | native, preview | Status and recorded delivery for your media buys. |
rdn_get_measurement | native | Closed-loop sales lift: store-holdout difference-in-differences on retailer transaction data, returning incremental revenue, lift and ROAS. |
Example: discover and activate a signal
Tool results carry the payload both as structuredContent and as JSON text in content[0].text. Every AdCP response carries status, message, timestamp and adcp_version, and echoes your context. Task-level failures return status: "failed" with errors[] (and adcp_error with JSON-pointer issues for validation) and isError: true: VALIDATION_ERROR, SIGNAL_NOT_FOUND, IDEMPOTENCY_CONFLICT, UNSUPPORTED_FEATURE, VERSION_UNSUPPORTED. Protocol failures return JSON-RPC errors (-32001 unauthorized, -32601 unknown method, -32602 unknown tool).