public API + webhooks.
everything yala’s admin UI does, you can do via REST. api keys are workspace-scoped Bearer tokens. webhooks are HMAC-SHA256-signed, replay-protected, and retried with exponential backoff. free at every tier.
getting an api key.
- go to workspace → developer.
- click + create key. pick a role (viewer / editor / admin) — it determines which routes the key can hit.
- yala generates a token like yla_live_abc123... (live) or yla_test_abc123... (test). copy it now. we hash it with SHA-256 server-side; we never show the plaintext again.
the admin shows a 12-char prefix so you can identify which key is which. revoke any time — server-side comparison fails on the next request.
authenticating a request.
every request: send the key as a Bearer token.
GET /v1/links HTTP/1.1 Host: api.yala.la Authorization: Bearer yla_live_abc123... Content-Type: application/json
the routes you’ll use.
full reference at api.yala.la/v1 with OpenAPI spec; the high-leverage subset:
- POST /v1/scanner/preview — preview a scan without writing anything. accepts source url / UPC / ISRC, returns destinations + artwork.
- POST /v1/links — create a link. accepts type, title, slug, defaultUrl, optional seedDestinations, optional seedArtworkUrl, optional source (kicks off a real scan job).
- GET /v1/links/{id} — read a link including destinations + redirects + landing config.
- PATCH /v1/links/{id} — update title / defaultUrl / fallbackUrl.
- POST /v1/links/{id}/publish — .../unpublish / .../archive / .../unarchive.
- POST /v1/links/{id}/destinations — upsert a destination row (DSP).
- POST /v1/links/{id}/redirects — create a conditional redirect.
- GET /v1/analytics/summary — workspace or per-link KPI summary.
- POST /v1/dsar/exportFan / eraseFan — GDPR Art. 15 + 17 endpoints. admin role only.
a real-world example.
scan a track + create a link in two calls (the wizard does exactly this):
# 1) preview the scan (no writes)
PREVIEW=$(curl -sX POST https://api.yala.la/v1/scanner/preview \
-H "authorization: Bearer $YALA_KEY" \
-H "content-type: application/json" \
-d '{
"source": {"kind": "url", "value": "https://open.spotify.com/track/abc"}
}')
# 2) create the link with the preview destinations seeded
curl -X POST https://api.yala.la/v1/links \
-H "authorization: Bearer $YALA_KEY" \
-H "content-type: application/json" \
-d "$(jq -n --argjson p "$PREVIEW" '{
type: "release",
title: "the b-side",
publish: true,
seedDestinations: $p.destinations,
seedArtworkUrl: $p.artworkUrl
}')"webhooks.
register an endpoint URL in workspace → developer → webhooks. on every event we POST a JSON payload signed with HMAC-SHA256. verify the signature server-side using your shared secret — the webhook setup UI shows the secret once at creation (rotatable later).
events we fire:
- link.created
- link.updated
- link.archived
- scan.completed
- fan.subscribed (email capture or pre-save)
- fan.unsubscribed
- broadcast.sent
verifying signatures.
the x-yala-signature header has the format v1=<hex>. compute HMAC-SHA256 over the raw request body using your secret and compare:
import crypto from "node:crypto";
function verify(rawBody: string, headerSig: string, secret: string) {
const [version, signature] = headerSig.split("=");
if (version !== "v1") return false;
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signature, "hex"),
Buffer.from(expected, "hex"),
);
}retry policy.
we retry up to 5 times with exponential backoff (1m, 5m, 30m, 2h, 8h). after the 5th failure we mark the delivery failed in the delivery log; you can replay it manually from the developer panel.
rate limits.
- read endpoints: 600/min per workspace.
- write endpoints: 120/min per workspace.
- scanner: 60/min per workspace.
429s come back with a Retry-After header. enterprise tier raises these on request.