Survey campaign API
The advertiser survey API is mounted at /api/v1/campaigns. It is intended for approved advertiser accounts integrating from their server. Dashboard users can follow the survey campaign workflow without calling these endpoints.
Authentication
Send your advertiser X-Api-Key over HTTPS. Requests also require a URL signature in the enc query parameter, derived from the advertiser secret and request body. The service rejects missing keys, unknown keys, pending advertiser accounts, and invalid signatures. Keep the key and secret on your server and validate the exact signing output with your RapidoReach integration contact before connecting traffic. Do not reuse a publisher application API key.
The external API signs the full request URL before adding enc, including any query filters, then the JSON serialization of a nonempty body, then the advertiser secret. Append the digest as the last ?enc=... or &enc=... field. The scheme, host, query encoding/order and JSON property order must match. The account's configured url_security_encryption_type selects SHA-1, SHA-256 or SHA3-256; legacy SHA3 signatures remain accepted. See the separate survey developer reference for endpoint-specific JSON schemas and examples. Test signing in development before automating a write.
For a current SHA3-256 account, a server can construct a request as follows. Confirm the algorithm and base URL for your account before use; this sample makes no network request.
const { createHash } = require('node:crypto');
const baseUrl = 'https://YOUR_DEVELOPMENT_HOST/api/v1/campaigns/create';
const body = {
name: 'Example study', country_language_id: 'YOUR_MARKET_ID',
cpi: 1.5, length_of_interview: 10, conversion: 20,
start_date: '2026-10-01', end_date: '2026-10-15',
survey_live_link: 'https://survey.example/live?transaction={transaction_id}',
survey_test_link: 'https://survey.example/test?transaction={transaction_id}',
max_daily_completes: 50,
};
const json = JSON.stringify(body);
const digest = createHash('sha3-256')
.update(baseUrl + json + process.env.RAPIDOREACH_ADVERTISER_SECRET)
.digest('hex');
const signedUrl = `${baseUrl}?enc=${digest}`;
// Send json as the POST body and X-Api-Key from protected server configuration.
Both survey links must contain the exact {transaction_id} macro. Preserve its resolved value throughout the survey and result redirects. Confirm accepted link formats with the dashboard and a development request.
Campaign endpoints
| Method | Path | Purpose |
|---|---|---|
| GET | /getcampaigns | List campaigns visible to the authenticated creator |
| POST | /searchcampaigns | Search campaigns |
| POST | /create | Create a draft campaign |
| GET | /:campaignId | Read a campaign |
| PUT | /:campaignId | Update a campaign, subject to route policy |
| POST | /clonecampaigns | Clone a campaign for a new study |
| DELETE | /:campaignId | Delete a campaign where policy allows |
Create and update validate the live and test survey link templates. A name on create must be at least four characters. Keep the live and test URLs separate and verify redirects before funding. Treat campaign IDs as opaque, and keep each advertiser's IDs and credentials separate. Do not use an ID alone as your own authorization check.
Create request fields
POST /create accepts a JSON body with the project fields below. Values must match the same market, pricing, and link assumptions used in the dashboard.
| Field | Purpose |
|---|---|
name | Internal campaign name, at least four characters |
country_language_id | Target country and language identifier |
cpi | Cost per completed interview |
length_of_interview | Expected minutes per interview |
conversion | Expected completion percentage |
start_date, end_date | Field dates |
survey_live_link, survey_test_link | Validated live and test survey link templates |
max_daily_completes | Daily completion limit |
supported_devices | Device eligibility list |
research_category, research_industry, campaign_manager, tags | Optional project metadata |
On success, create returns HTTP 201 with campaign and creator objects; the creator response includes a test_redirect_url. Use that test URL to check outcomes before funding. Invalid input or signing prevents creation. Treat response IDs and test URLs as opaque; do not build new URLs from their internal structure.
{
"message": "Campaign created successfully",
"campaign": {"_id": "CAMPAIGN_ID", "name": "Example study"},
"creator": {"_id": "ADVERTISER_USER_ID", "test_redirect_url": "/test/survey/..."}
}
Quotas and screening
| Method | Path | Purpose |
|---|---|---|
| GET | /:campaignId/getcampaignquota | List campaign quotas |
| POST | /:campaignId/campaignsquota | Create a quota |
| GET / PUT / DELETE | /:campaignId/campaignsquota/:campaignQuotaId | Read, update, or remove a quota |
| GET | /:campaignId/getcustomquestions | List custom screeners |
| POST | /:campaignId/customquestion | Create a screener |
| GET / PUT / DELETE | /:campaignId/customquestion/:customquestionId | Read, update, or remove a screener |
| POST | /:campaignId/clonecampaignsquota | Clone a campaign quota |
| GET | /:campaignId/campaignsquota/:campaignQuotaId/getcampaignsqualifications | List qualifications |
| POST | /:campaignId/campaignsquota/:campaignQuotaId/campaignsqualification | Add a qualification |
| GET / PUT / DELETE | /:campaignId/campaignsquota/:campaignQuotaId/campaignsqualification/:campaignQualificationsId | Read, update, or remove a qualification |
| POST | /cq/:customquestionId/createoption | Add a screener answer option |
| PUT / DELETE | /cq/:customquestionId/option/:option_id | Update or remove an answer option |
POST /:campaignId/campaignsquota accepts name and num_respondents in JSON and returns 201 with campaignQuota. POST /:campaignId/clonecampaignsquota takes {"quotaId":"SOURCE_QUOTA_ID"}. A new custom question and a new answer option are initialized with defaults; update the returned IDs with the question and answer text and acceptance rules before using them to screen respondents. Read the saved quota and question back before assigning supply or funding.
Additional endpoints: POST /listcountrylanguage lists supported markets; POST /getProfilingQuestionsForTargeting returns profiling catalog data; GET /:campaignId/getcustomquestionsforprofiling returns campaign screeners for profiling; GET /downloadresponses downloads responses; GET /invoices lists invoices. These depend on campaign state and account configuration. Start with reads in development, then test a complete draft, quota, screener, redirect, and funding flow before API writes. API creation alone does not activate or fund a campaign. See survey API errors and checks.