Skip to main content
Version: v2

Publisher callback and operations API

These /publisher/v2 configuration and reporting routes use a publisher dashboard bearer session. The actual reward event is a server-to-server delivery from RapidoReach to the HTTPS endpoint you configure. See the reward callback guide for crediting rules.

Callback configuration​

MethodPathPurpose
PUT/placements/{placementId}/callbackSet HTTPS endpoint, callback families, optional IP allowlist and failed redirect URL
POST/placements/{placementId}/callback/rotateStage a new one-time secret and key ID; returns 201
POST/placements/{placementId}/callback/promotePromote the staged key after its valid time
POST/placements/{placementId}/callback/testReturn a signed in-memory sample; does not deliver externally

enabledFamilies accepts REWARD_PENDING, REWARD_CONFIRMED, and REWARD_REVERSED. The current callback signature version is HMAC_SHA256_V1. The signed value is HMAC-SHA256 over timestamp.nonce.canonicalJsonBody using the secret identified by keyId. Require a fresh timestamp and nonce, compare signatures safely, and deduplicate by event/transaction identity before crediting. A test response reports deliveredExternally: false and includes a sample payload and headers object; it creates no accounting entry.

The live delivery is an HTTPS JSON POST to your configured endpoint. Headers are X-RapidReach-Key-Id, X-RapidReach-Timestamp (ISO date/time), X-RapidReach-Nonce, X-RapidReach-Signature (lowercase hex), and Idempotency-Key. The canonical body is JSON with object keys sorted recursively, retaining array order; do not hash the raw received byte stream or a differently ordered JSON serialization. The callback payload contains:

FieldMeaning
schemaVersion, callbackTypeCurrent contract version and REWARD_CONFIRMED or REWARD_REVERSED delivery type.
transactionId, originalTransactionIdReward ID and, for reversal, the original reward ID.
placementId, adSlotId, externalUserId, campaignIdIdentity to reconcile with your ledger and the SDK session.
virtualAmountMinorUnits, virtualCurrencyPublisher-defined user reward and currency.
usdPayoutMicros, status, sandbox, occurredAtPayout amount, reward state, environment, event time.
{
"schemaVersion": "2.0.0",
"callbackType": "REWARD_CONFIRMED",
"transactionId": "REWARD_TRANSACTION_ID",
"originalTransactionId": null,
"placementId": "PLACEMENT_ID",
"adSlotId": "SLOT_ID",
"externalUserId": "user-123",
"campaignId": "CAMPAIGN_ID",
"virtualAmountMinorUnits": 50,
"virtualCurrency": "Coins",
"usdPayoutMicros": 750000,
"status": "CONFIRMED",
"sandbox": false,
"occurredAt": "2026-09-29T08:00:00.000Z"
}

Persist the callback event and apply a confirmed credit or linked reversal in one idempotent transaction, then return any 2xx response. A non-2xx response triggers a retry; deliveries stop after the configured attempts and can enter a dead-letter state. Keep both the Idempotency-Key and transaction IDs so an operator replay cannot double-credit. The sample payload above is illustrative; use the current body and headers from the test endpoint to verify your implementation.

PUT /publisher/v2/placements/PLACEMENT_ID/callback
Authorization: Bearer SESSION_TOKEN
Content-Type: application/json

{
"endpoint": "https://publisher.example/rewards/callback",
"enabledFamilies": ["REWARD_CONFIRMED", "REWARD_REVERSED"],
"ipAllowlist": []
}

The secret returned by /callback/rotate is displayed once. Store the current and next keys during overlap; the staged key becomes valid at validFrom, and promotion is blocked until then. Never use a dashboard session or Static API key as the HMAC secret.

Delivery and report endpoints​

MethodPathResponse
GET/callback-deliveries?status={items,count} without full payloads
GET/callback-deliveries/{deliveryId}One delivery with user ID redacted
POST/callback-deliveries/{deliveryId}/replayReplay result; requires Idempotency-Key and a reason
GET/reports/offersJSON metrics, settled rewards, freshness watermark, reconciliation
GET/reports/offers?format=csvCSV attachment with reward and ledger totals
GET/offer-gallery?placementId=&adSlotId=&country=&platform=Preview inventory for an owned Offerwall or Offer API slot

A callback replay may queue a DEAD_LETTER, RETRY_WAIT, or already DELIVERED item. Reusing its idempotency key returns duplicate: true. Your receiver must still deduplicate the delivery. A nonzero reconciliation.differenceMicros or exact: false needs investigation against ledger and callback state before final reporting.

The replay body is {"reason":"Receiver recovered after outage"}; a reason is 3–240 characters. GET /callback-deliveries accepts status and returns at most 100 newest records. Use one delivery's lastErrorCode, attempt count, next attempt, and response status to diagnose the receiver. Treat a DELIVERED status as delivery acknowledgment, not proof that your own balance update succeeded.

Offer operations are gated by the offer delivery capability. Review a 404 not_found against environment availability before treating it as a missing placement.