Developer docs

Deliver targeted ads over HMAC HTTPS

Integrate Meridian Ads with an SDK or signed HTTP. These pages are the English contract for publishers and integrators.

Meridian Ads is a real-time ad serving product from Yelle Software. Publishers send a user_key plus a small context map. Advertisers target those traits with prepaid USD credits and a CPM. Every creative is moderated before it can fill a live placement.

Intended production hosts: meridianads.tech for this console and these docs, api.meridianads.tech for the control plane, and serve.meridianads.tech for decision, events, and click redirects.

POST /v1/decision

Client

Redis index

Adserver

200 JSON or 204

Creative

Core serving endpoint

HMAC required

HMAC required. 200 is a paid or house fill. 204 is no fill. 429 if the app_key exceeds 100 decisions per second.

POSThttps://serve.meridianads.tech/v1/decision

Local http://localhost:8090/v1/decision

Request payload

The public app key prefix travels in X-App-Key, not in the JSON body.

Field Type Required Description
placementstringRequiredPlacement name on the authenticated app.
user_keystringRequiredOpaque publisher identifier. Hashed at rest if it looks like email. Never put this on a landing URL.
contextobjectOptionalTrait map merged last-write-wins. Max 8KB JSON. Missing traits fail closed.

Code

SDK and cURL

HMAC, timestamps, and the canonical string are handled by the client. Prefer an SDK. cURL is the raw contract.

import { MeridianAds } from '@meridianads/sdk'

const client = new MeridianAds({
  appKey: process.env.MERIDIAN_ADS_APP_KEY,
  secret: process.env.MERIDIAN_ADS_SECRET,
  // baseUrl: 'http://localhost:8090'
})

const decision = await client.serve('home_banner', 'user-42', {
  country: 'US',
  plan: 'pro'
})

if (!decision) {
  // HTTP 204: no paid or house fill
} else {
  await client.recordImpression(decision)
}

Response schemas

native_text and image

Meridian Ads returns JSON. You render it. Formats are native_text and image. IDs below are synthetic examples for the docs.

native_text

JSON
200 fill · synthetic ids
{
  "campaign_id": "3b2e0c6a-4d11-4b0a-9c2e-0f1a2b3c4d5e",
  "house": false,
  "creative": {
    "id": "7aa1b2c3-d4e5-6789-abcd-ef0123456789",
    "format": "native_text",
    "click_url": "https://serve.meridianads.tech/v1/click/{token}",
    "impression_token": "imp_…",
    "native": {
      "headline": "Example native headline",
      "body": "Synthetic copy for the docs.",
      "cta": "Learn more"
    }
  }
}

Example render

Example native headline

Synthetic

Synthetic copy for the docs.

Learn more →

image

300×250
200 fill · synthetic ids
{
  "campaign_id": "3b2e0c6a-4d11-4b0a-9c2e-0f1a2b3c4d5e",
  "house": false,
  "creative": {
    "id": "8bb2c3d4-e5f6-7890-bcde-f01234567890",
    "format": "image",
    "click_url": "https://serve.meridianads.tech/v1/click/{token}",
    "impression_token": "imp_…",
    "image": {
      "cdn_url": "https://cdn.meridianads.tech/…",
      "alt": "Example banner",
      "width": 300,
      "height": 250,
      "mime": "image/webp"
    }
  }
}

Example render

Example banner

cdn.meridianads.tech

Learn more

Review gate

Live serve only uses approved creatives. If the moderator is down, the creative stays pending_review. Staff override is audited.

approved

Can fill live

pending_review

Waiting. Fail closed.

rejected

Cannot fill

Guides

Locked serve loop

  1. 1

    Authenticate with an app key prefix plus HMAC-SHA256.

  2. 2

    Call POST /v1/decision with placement, user_key, and context.

  3. 3

    Render the creative. Fire POST /v1/events with the impression token.

  4. 4

    Send clicks through the signed click_url. Adserver 302s to the landing.