BlendPartner API
blendapp.ai

Getting started

OverviewQuickstartHow the integration worksAuthenticationAny backend

Catalog

Listing eventsEvent detail & ticketsWhich events you see

Checkout

Buyer sessionsInventory & seat holdsReserving an orderTaking the paymentConfirming & settlement

Mobile apps

Native UI (no webview)Embedding the webviewiOS (Swift)Android (Kotlin)React Native

Reference

ErrorsRate limitsTesting & go-live

Quickstart

Build it in this order and every step is verifiable before you start the next one. You can get through steps 1 and 2 with nothing but a terminal.

Before you start

You need a channel key, a channel secret, and a signing key. Blend sends these by email; they are never published in this documentation. Keep the secret and the signing key on your servers.

1. Prove your credentials work

The catalog endpoint is the cheapest thing to call and needs nothing but your key pair. If this returns events, your credentials, your IP allowlist and your catalog are all correct.

curl https://api.blendapp.ai/api/v1/channel/events \
  -H "x-blend-key: ck_live_xxxxxxxxxxxxxxxx" \
  -H "x-blend-secret: cs_live_xxxxxxxxxxxxxxxx"

An empty list is a valid answer, it means no events have been added to your channel yet, not that anything is broken. A 401 means the key pair is wrong; a 403 means your IP is not on the allowlist.

2. Mint a buyer session

A session is a short-lived, single-use URL tied to one buyer. Your backend mints it; your app opens it.

curl -X POST https://api.blendapp.ai/api/v1/channel/session \
  -H "x-blend-key: ck_live_xxxxxxxxxxxxxxxx" \
  -H "x-blend-secret: cs_live_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"buyerName":"Rami Damianos","buyerEmail":"rami@example.com"}'
Sessions are single use and expire in 30 minutes

Mint one when the user opens your events tab, not at app launch. Do not cache the URL across users, it carries that buyer’s identity.

3. Open it in a webview

Load the URL. Blend renders the catalog, event pages, seat maps and checkout. There is nothing to build here beyond hosting the webview and registering the payment bridge in the next step.

iOS (Swift)WKWebView setup, copy-paste.Android (Kotlin)WebView setup, copy-paste.React Nativereact-native-webview setup.
Powered byBlend

4. Register the payment bridge

When the buyer taps Pay, Blend reserves the order and hands your native code an order id and an amount to display. Register the handler before you load the URL, or the Pay button will correctly report that it has nowhere to send the charge.

The message your app receives
{
  "type":     "charge",
  "orderId":  "6a9b1c.e42",
  "amount":   42.5,
  "currency": "USD"
}
Display this amount, do not charge it

Treat the payload as a display hint only. Before charging, have your backend read the authoritative total for that orderId from Blend and charge that number. Taking the payment explains why in one short section.

5. Charge, then confirm

Charge the buyer on your own rail. When it succeeds, your backend tells Blend, signed, server to server. Blend issues the ticket, and the webview, which has been polling, shows it to the buyer within a few seconds.

import crypto from "node:crypto";

const orderId          = "6a9b1c.e42";
const amount           = 42.5;
const partnerReference = "toters_charge_88213";      // your own charge id

const signature = crypto
  .createHmac("sha256", process.env.BLEND_SIGNING_KEY)
  .update(`${orderId}.${amount.toFixed(2)}.USD.${partnerReference}`)
  .digest("hex");

const res = await fetch(
  "https://api.blendapp.ai/api/v1/channel/orders/confirm",
  {
    method: "POST",
    headers: {
      "x-blend-key": process.env.BLEND_KEY,
      "x-blend-secret": process.env.BLEND_SECRET,
      "x-blend-signature": signature,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ orderId, amount, partnerReference }),
  },
);

6. Handle the two failures that matter

  1. Confirm did not return a success

    If you get 503 ACCRUAL_FAILED_RETRY, retry, it is safe. If you get 409 CONFIRM_FAILED with refundRequired, refund the buyer: no ticket was issued.

  2. You are not sure whether it went through

    Never guess. Ask: POST /v1/channel/orders/status with the order id returns paid, pending or failed. Confirm is idempotent, so retrying is always safer than assuming.

ErrorsEvery code, and what to do about it.Testing & go-liveHow to verify before launch.Confirming & settlementThe full confirm contract.
Powered byBlend© 2026 Blend · Ticketing & event infrastructure