Publisher API

Integration guide

Step-by-step publisher integration — portal configuration, API calls, displaying offers, and handling survey returns.

Overview

A typical integration has three parts:

  1. Configuration in the Publisher Portal (one-time per app).
  2. Offer requests from your backend when a panelist opens your survey wall or a single-offer flow.
  3. 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:

SettingPurpose
Complete URLPanelist successfully finished the survey
Screen-out URLPanelist did not qualify
Cancelled URLRequired. Reserved for sessions that end without a result; mypinio does not currently redirect panelists to it. Never credit a reward here
Redirect signing secretShared 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/surveys

Minimum 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_KEY

or

X-API-Key: YOUR_API_KEY

Details: Authentication.

Optional request fields

FieldWhen to use
maxSurveysLimit how many offers are returned (capped at your account limit; if omitted, up to that limit)
profileDetails.postalCode, cityImprove matching (age and gender are required, see above)
subId1, subId2, subId3Your own tracking IDs, passed through the session
surveyId / sidRequest 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 userRewardAmount and rewardUnitName if you display rewards.
  • Open entryLink when 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:

ParameterDescription
appIdYour app
panelistIdYour user ID
entryLinkCodeShort code for the offer wall entry used
reasonOn screen-out only: overquota, qualification_mismatch, or security
tsUnix timestamp (seconds) when the link was signed
sigHMAC-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
  • entryLink opened in browser/WebView; no secrets in the link
  • Return URLs verify sig before side effects (rewards, status updates)
  • Each entryLinkCode credited at most once; redirect_probe_test never credited
  • profileDetails.age (number) and profileDetails.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 / rewards

For a minimal curl example, see Quickstart.

On this page