Skip to content
Hosted offerwall

A wall we host, opened with a URL.

The simplest integration and the one everything else is built on. You create a placement, you get an id, and that id is a web address. Sign it for your user on your server, put it in an iframe, a new tab or a webview, and your users have a wall.

Working today

  • Applications for a publisher account are open and read by a person.
  • The hosted wall at wall.opuswall.net/<placement-id>, in English and Turkish, in your currency and your colours, with signed URLs and each user's own activity.
  • The click redirect and the signed server postback, retried on a fixed schedule and logged attempt by attempt in your panel, with test postbacks you send yourself.
  • The publisher panel, where a placement, its wall key and its postback secret are created, and where every parameter below is shown with your own placement filled in.

Still being built

  • Supply: the network is new, so campaigns arrive in the wall as advertisers are approved and funded — and a wall with nothing to list says so to the user.

How to read this page

Sections marked Planned describe a contract we are building to, published early so you can design against it. Sections with no badge are running today, exactly as written. We will tell you in writing before anything marked Planned changes.

The wall URL

A placement id is a UUID and it is public — it appears in the address bar of the wall. It is not a secret and it does not authenticate anything. Your wall key, which signs the URL, and your postback secret, which signs our calls to you, never leave your server.

  • An iframe is the usual choice for a website. Offers open in a new tab, so a sandboxed frame must allow popups to escape the sandbox.
  • In an Android or iOS webview, open anything that is not the wall — the offer itself, store links — outside the webview. Your placement's page has the code for both.
  • The same user id must always mean the same person, because that is what the postback returns to you.
A signed wall URL — the integration guide's worked example, with an example key
https://wall.opuswall.net/fbefb48b-df2e-4102-9e05-f48c4083edc2
  ?sub_id1=summer-2026&sub_id2=&sub_id3=
  &timestamp=1790000000
  &user_id=player%2048213
  &signature=6ce59c3587e22f8f83e0dea539e833c7947f240280badf2f6149a83706bc89bc

wall key   5d0f6c8e2b4a19377c1e9f0a3b6d8c2e4f7a9b1c3d5e7f80a2c4e6f8b1d3f5a7 (an example)
canonical  sub_id1=summer-2026&sub_id2=&sub_id3=&timestamp=1790000000&user_id=player%2048213

What you pass in

Two things reach the wall from you: which placement it is, in the path, and who is looking at it. The rest is optional and comes back to you on the postback, or only changes the wall's own language.

Sign the URL on your server with the placement's wall key, and turn on signed URLs in your panel: until you do, anybody can open your wall as any user id they type. A signed URL is valid for 24 hours and also opens the user's own activity on the wall — treat it like a session link.

Wall URL parameters

  • user_id

    Required
    Required
    Meaning
    Your own identifier for the user, 1–120 characters. Opaque to us — an internal id, never an e-mail address or a name. Signed.
  • sub_id1, sub_id2, sub_id3

    Required
    Optional
    Meaning
    Your own tracking values, up to 120 characters each. Returned unchanged on the postback. Signed, as empty when absent.
  • timestamp

    Required
    With a signature
    Meaning
    Unix seconds when you built the URL. Signed.
  • signature

    Required
    When your placement requires it
    Meaning
    Lower-case hex HMAC-SHA256 of sub_id1, sub_id2, sub_id3, timestamp and user_id, keyed with your wall key.
  • lang

    Required
    Optional
    Meaning
    en or tr forces the wall's own text into that language; otherwise the browser's language decides. Not signed.

Signing: one rule for everything

Take the fixed list of keys for the request, every one of them — a key with no value is signed as the empty string. Sort them by byte value. Write each as key=value with the value percent-encoded per RFC 3986: the UTF-8 bytes of A–Z a–z 0–9 - . _ ~ as they are, every other byte as %XX in upper case, so a space is %20, never +. Join them with &.

The signature is the lower-case hex HMAC of that string — SHA-256 unless your secret's settings say SHA-512 — keyed with the secret exactly as it was issued: the 64-character hex string, used as text. The canonical string is itself a valid query string, so what is signed and what is sent can never drift apart.

  • Timestamps are Unix seconds. A signed request is accepted while it is at most 24 hours old and at most 5 minutes ahead of our clock.
  • Signatures are compared in constant time and without regard to case.
  • Every secret is 64 hex characters from the database's own random generator, shown once when it is issued, and never readable afterwards — lose one and you rotate it.
Test vector — check an implementation against this first
key        a3f1c2d4e5b6978812345678901234567890abcdefabcdefabcdefabcdef0123

params     campaign_name = Çay 🎉 %20 ğüşİı
           sub_id1       = it's (a) *test*!
           sub_id2       = ~._-AZaz09
           sub_id3       = (empty)
           timestamp     = 1790000000
           user_id       = user 1+2/ü?&=

canonical  campaign_name=%C3%87ay%20%F0%9F%8E%89%20%2520%20%C4%9F%C3%BC%C5%9F%C4%B0%C4%B1&sub_id1=it%27s%20%28a%29%20%2Atest%2A%21&sub_id2=~._-AZaz09&sub_id3=&timestamp=1790000000&user_id=user%201%2B2%2F%C3%BC%3F%26%3D

HMAC-SHA256  fb12087ed404c88d11251ab7c46dec60db6e7c249cc5354039b0955c83b73b59

What the advertiser receives

When a user opens an offer, we record a click and send them to the advertiser's tracking URL with our macros filled in and percent-encoded. The advertiser sends the click id back when a goal completes, which is what ties a conversion to one user, one placement and one moment.

Your user_id reaches the advertiser only if their tracking URL asks for it through {external_user_id} — which is one reason it must be an opaque internal id, never a name or an address. Beyond the macros their tracking URL asks for, they receive only what any website sees when the user's browser opens it.

Macros we substitute into the advertiser's tracking URL

  • {click_id}

    Meaning
    The click. The value the advertiser must return to confirm a goal.
  • {placement_id}

    Meaning
    Which publisher placement produced the click.
  • {campaign_id}

    Meaning
    Which campaign was opened.
  • {goal_id}

    Meaning
    The goal the click was opened for.
  • {external_user_id}

    Meaning
    Your user_id, as it arrived on the wall URL.
  • {sub_id1}, {sub_id2}, {sub_id3}

    Meaning
    Your sub ids, empty if none.
  • {country}

    Meaning
    The visitor's two-letter country, or empty when it is not known.
  • {platform}

    Meaning
    ios, android, desktop or web.

The postback you receive

When a conversion from your wall settles — the advertiser confirmed it and the money moved — we call the postback URL on your placement, https only. When a settled conversion is reversed, we call it again so you can take the reward back. GET appends the parameters to your URL's query; POST sends them as a form body. Your placement's page shows every attempt with your server's answer, and sends test postbacks.

All fifteen parameters are always present, empty when there is nothing to send, followed by signature: the HMAC of the fifteen, in the order above, with your placement's postback secret. Verify it, and refuse a timestamp more than an hour old — we sign every attempt as it leaves.

  • Acknowledge with any 2xx status and a body of exactly OK or 1. Anything else — another body, a redirect, an error, no answer within 10 seconds — is a failed attempt.
  • A failed attempt is retried after 1 minute, 5 and 15 minutes, 1, 3, 6 and 12 hours, then 24 hours twice: ten attempts over about three days. An abandoned notice can be re-queued from your panel for 30 days.
  • Credit once per (transaction_id, status), under a unique constraint in the same transaction as the credit. On a reversal, take back only what you credited; if you never did, answer OK and do nothing.
  • We never send a credit after its reversal, or a reversal for a credit that never left us.
  • We call only public addresses: your hostname is resolved once per attempt and refused if any address it resolves to is private, loopback, link-local or reserved. We connect to the address we checked, follow no redirect and read at most 16 KiB.
Example request (an example secret and illustrative values)
GET https://example.com/opuswall/postback?site=main
  &amount=1750
  &campaign_id=4a3a4905-900d-4fb1-b719-432d3e292085
  &campaign_name=Example%20campaign
  &goal_id=0f5b8d2e-6c1a-4e9b-b3d7-5a2c8e4f1b90
  &goal_name=Example%20goal
  &placement_id=fbefb48b-df2e-4102-9e05-f48c4083edc2
  &share_usd_cents=175
  &status=credit
  &sub_id1=summer-2026&sub_id2=&sub_id3=
  &test=0
  &timestamp=1790000000
  &transaction_id=c8e1b0d4-7a2f-4c6e-9b3d-1e5f7a9c2b4d
  &user_id=player%2048213
  &signature=60996fe5750f91e727d8d1acbb1afc765f4284d6fecf377f941e900d8eab91ab

Secret e1d2c3b4a5968778695a4b3c2d1e0f1a2b3c4d5e6f708192a3b4c5d6e7f80912 (an example).
Broken over lines for reading; sent as one. Your own site=main is not signed.

Postback parameters

  • amount

    Meaning
    What to credit, or take back, in whole units of your currency: floor(share_usd_cents × coins_per_usd ÷ 100). It can be 0.
  • campaign_id, campaign_name

    Meaning
    The campaign, and its name as it stood when the conversion was recorded.
  • goal_id, goal_name

    Meaning
    The completed goal.
  • placement_id

    Meaning
    Your placement.
  • share_usd_cents

    Meaning
    Your earnings for this conversion, in US cents — already split.
  • status

    Meaning
    credit, or reversal.
  • sub_id1, sub_id2, sub_id3

    Meaning
    As they arrived on the wall URL, empty if they did not.
  • test

    Meaning
    1 for a test postback, 0 for a real one. Never credit a 1.
  • timestamp

    Meaning
    Unix seconds when this attempt was signed.
  • transaction_id

    Meaning
    Our id for the conversion — identical on every attempt, and on its credit and its reversal.
  • user_id

    Meaning
    The user_id from your wall URL.
  • signature

    Meaning
    Lower-case hex HMAC of the other fifteen, with your postback secret.

How the wall looks

The wall is built to sit inside your product rather than next to it: your currency name, your exchange rate, your accent colour, and a light, dark or automatic appearance, all set on the placement. It speaks English and Turkish, and a user can switch between them on the wall.

Offers are listed only when their targeting, the advertiser's funding and the campaign's budget allow it. Country targeting needs the visitor's country: a visitor whose country is not known is shown only offers open to every country.

There are no wheels, boxes or chance mechanics anywhere in it. Offers are apps, games, surveys and tasks, and a user always knows what they have to do before they start.

Hosted offerwall

Start with the simplest one

Most publishers never need anything beyond this page. Apply, and once your account is open your placement's page has every value above filled in for you.