Integration guide
Step-by-step publisher integration — portal configuration, API calls, displaying offers, and handling survey returns.
Overview
A typical integration has three parts:
- Configuration in the Publisher Portal (one-time per app).
- Offer requests from your backend when a panelist opens your survey wall or a single-offer flow.
- Return handling on URLs you host, after the panelist leaves a live survey.
Your mobile app or website should never call the Publishers API directly or store API keys. All API traffic goes server-to-server.
Step 1 — Portal configuration
Sign in at publishers.mypinio.com and complete the following for each app you integrate.
Create or select an app
Each integration uses an appId (shown in the portal under Apps). Use the same appId in every API request for that property.
Configure redirect URLs
Under Apps → your app → Settings, set:
| Setting | Purpose |
|---|---|
| Complete URL | Panelist successfully finished the survey |
| Screen-out URL | Panelist did not qualify |
| Cancelled URL | Required. Reserved for sessions that end without a result; mypinio does not currently redirect panelists to it. Never credit a reward here |
| Redirect signing secret | Shared secret (min. 16 characters) used to sign return URLs |
All four are required before the surveys API returns offers. See Redirect URLs for URL templates and signature verification.
Then click Test redirects in the same settings page: mypinio sends one signed test request to each URL (panelist ID redirect_probe_test). The portal shows the HTTP status your server answered; check in your own logs that your signature check accepted the request, and never credit redirect_probe_test.
Create an API key
Under Settings → API keys, create a key and store it in your secrets manager. The full key is shown only once.
Try in Postman
Local docs: use Download collection and import the file in Postman (File → Import). Run in Postman needs the public URL at publishers.mypinio.com — Postman cannot fetch collections from localhost.
Import the collection, set api_key, app_id, and panelist_id in Variables, then send List survey offers.
Step 2 — Request survey offers
From your backend, call:
POST https://publishers.mypinio.com/api/v1/publishers/surveysMinimum JSON body (profileDetails.age and profileDetails.gender are required from 2026-10-06):
{
"appId": "YOUR_APP_ID",
"panelistId": "YOUR_USER_ID",
"country": "DE",
"locale": "de-DE",
"profileDetails": { "age": 34, "gender": "female", "postalCode": "10115" }
}appId and panelistId are strings. gender is "male" or "female"; age is a JSON number. Details: profileDetails.
Use a stable panelistId — your own user identifier for that panelist. mypinio uses it to match profiling and suppress duplicate offers.
Authentication
Send your API key in every request:
Authorization: Bearer YOUR_API_KEYor
X-API-Key: YOUR_API_KEYDetails: Authentication.
Optional request fields
| Field | When to use |
|---|---|
maxSurveys | Limit how many offers are returned (capped at your account limit; if omitted, up to that limit) |
profileDetails.postalCode, city | Improve matching (age and gender are required, see above) |
subId1, subId2, subId3 | Your own tracking IDs, passed through the session |
surveyId / sid | Request one specific offer instead of a list |
Full reference: POST /surveys.
Step 3 — Use the response in your product
Success with offers
When requestStatus is "true" and hasSurveys is true, use the surveys array:
- Show
userRewardAmountandrewardUnitNameif you display rewards. - Open
entryLinkwhen the user selects a survey (browser tab, in-app WebView, or external browser). - Open the link from the user's tap — never prefetch or resolve it on your server, and request a fresh list per wall visit. In a WebView, allow JavaScript, cookies and redirects to other domains (WebView requirements).
Surveys are sorted by reward value (highest first).
Base profile questions (profilingUrl — legacy)
The response may still include profilingUrl. This field is deprecated and kept only for backward compatibility; it will be removed in a future API version.
Do not build new integrations around profilingUrl. Show surveys and partlySurveys as usual. When the panelist opens any entryLink, mypinio runs any missing base profile questions inline before starting the survey.
If you already use profilingUrl, you may keep doing so until we announce removal. Opening it before the offer list still works but is no longer the recommended path.
No matching surveys
HTTP 200 with hasSurveys: false and an empty surveys array is normal — show an empty state, not an error page.
Step 4 — Handle survey returns
When a panelist exits a live survey, mypinio redirects the panelist's browser to the Complete or Screen-out URL you configured (depending on outcome). This signed redirect is how mypinio reports each result — there is no separate server-to-server call, so treat the request to your Complete URL as your postback: verify it, then credit.
Your URL receives query parameters including:
| Parameter | Description |
|---|---|
appId | Your app |
panelistId | Your user ID |
entryLinkCode | Short code for the offer wall entry used |
reason | On screen-out only: overquota, qualification_mismatch, or security |
ts | Unix timestamp (seconds) when the link was signed |
sig | HMAC-SHA-256 hex signature |
Verify sig on your server before crediting rewards or updating session state. Algorithm: Verify return signatures.
Implement separate handlers (or one handler with branching) for complete vs screen-out URLs. Credit each entryLinkCode at most once — panelists reload pages and browsers retry. Code examples in Node.js, Python and PHP: Verify return signatures.
Step 5 — Go live checklist
The portal checks most of this for you: Apps → your app → Integration check shows, from your live traffic, whether requests arrive, lists contain surveys, participants open them and the first complete came back — and flags common problems with the fix. Problems and answers: Troubleshooting & FAQ.
- Redirect URLs and signing secret saved for each
appId - API key stored server-side only
- Surveys API called from backend, not from client apps
-
entryLinkopened in browser/WebView; no secrets in the link - Return URLs verify
sigbefore side effects (rewards, status updates) - Each
entryLinkCodecredited at most once;redirect_probe_testnever credited -
profileDetails.age(number) andprofileDetails.gender(male/female) sent on every request - Empty inventory (
hasSurveys: false) handled gracefully - Error responses logged; 502/504 retried with backoff
Example sequence
Your panelist opens survey wall
↓
Your server → POST /api/v1/publishers/surveys
↓
Response with surveys[] and partlySurveys[]
↓
User opens entryLink → live survey
↓
User completes or screens out
↓
Browser → your Complete or Screen-out URL (?appId&panelistId&…&sig)
↓
Your server verifies sig → update panelist / rewardsFor a minimal curl example, see Quickstart.