Warming up the decks…
Warming up the decks…
BlendPartner APIblendapp.aiThere is no Blend SDK to install and no runtime requirement. If your server can make an HTTPS request and compute an HMAC, it can integrate Blend. Both are in the standard library of every language below.
Three things, and none of them need a library:
That is the whole server side. Everything a ticketing system normally makes you build, inventory, seat state, price calculation, ticket delivery, has no counterpart on your side because you never hold a copy of it.
The signature covers the amount formatted to exactly two decimal places, with a full stop as the decimal separator. In Java and .NET the default formatter is locale-aware, so on a server set to German, French, Turkish or most of Europe, 42.5 formats as 42,50 and every signature you produce is wrong.
It fails as 401 INVALID_SIGNATURE, it usually passes on a developer machine set to English, and it appears the moment you deploy to a server with a different locale. Every sample below pins the locale explicitly. This is the single most common cause of a failing confirm call.
Build the string orderId.amount.USD.partnerReference, with the amount at two decimals, then HMAC-SHA256 it with your signing key and send the hex digest as x-blend-signature.
import crypto from "node:crypto";
// toFixed is not locale aware, so this is safe everywhere.
const payload = `${orderId}.${amount.toFixed(2)}.USD.${partnerReference}`;
const signature = crypto
.createHmac("sha256", process.env.BLEND_SIGNING_KEY)
.update(payload, "utf8")
.digest("hex");Run your signing code against this vector. If you get the same digest, your formatting, encoding and HMAC are all correct, and a real confirm will verify. If you get something else, the cause is almost always the decimal separator.
signing key csig_live_0000000000000000000000000000000000000000000000000000000000000000
orderId ord_test_0001
amount 42.5 formats to 42.50
currency USD
reference ref_test_0001
payload ord_test_0001.42.50.USD.ref_test_0001
expected 5603e012acdd557282c8c771b1169f714b6dcfb99fd9b208a5e3c6a0555d00e5The digest above was produced independently in Node, Python and Ruby and is byte for byte identical in all three. It is a real HMAC of a real payload with a throwaway key, so you can rely on it as ground truth.
Hold the amount as decimal in .NET, BigDecimal in Java,Decimal in Python, integer minor units in Node or Go. Binary floats cannot represent every two decimal value exactly, and a total assembled from floats can format one step away from the amount Blend holds. The confirm call allows a tolerance of 0.01, so this rarely bites, but it is free to avoid.
Both endpoints take JSON and the same two auth headers, so any HTTP client will do. There is nothing stack specific about them.
POST https://api.blendapp.ai/api/v1/channel/session
x-blend-key: ck_live_xxxxxxxxxxxxxxxx
x-blend-secret: cs_live_xxxxxxxxxxxxxxxx
Content-Type: application/json
{"buyerName":"Rami Damianos","buyerEmail":"rami@example.com"}
POST https://api.blendapp.ai/api/v1/channel/orders/confirm
x-blend-key: ck_live_xxxxxxxxxxxxxxxx
x-blend-secret: cs_live_xxxxxxxxxxxxxxxx
x-blend-signature: <hex digest from above>
Content-Type: application/json
{"orderId":"ord_9f2c","amount":42.5,"partnerReference":"toters_88213"}Generate one per buyer action and reuse the same value when you retry. A retry with a fresh key is a second order; a retry with the same key returns the original. See Reserving an order.