Access Mode B — Partner integration guide
Hand this to any third-party / sister app that unlocks content when buyers pay on ELKNZ Access (وصول).
Access = buyer pays on ELKNZ. Partner unlocks their product.
Not Mode A (“Pay with Elknz” on your site) — see Pay with Elknz.
What you need from the seller listing
| Field | Purpose |
|---|---|
external_ref | Your plan / SKU code (sent on webhooks + verify) |
partner_api_secret (aks_…) | HMAC webhooks + X-Elknz-Access-Secret |
webhook_url | Primary unlock path |
claim_url (optional) | Browser redirect after pay with ?claim=… |
Seller sets these on the Access listing (dashboard). Rotate secret via seller API when needed.
Recommended integration (webhook-first)
Buyer pays on elknz.com/access/…
→ ELKNZ wallet debit
→ POST your webhook access.paid | access.renewed | access.expired
→ You upsert entitlement by elknz_user_id + external_ref
Buyer opens your app later
→ You call POST /api/access/verify-entitlement (no key paste)
→ Unlock if valid: true
Fallback: buyer pastes elk_… → POST /api/access/verify-key
Optional UX: claim_url redirect → POST /api/access/claimTreat duplicate event_id as already processed. On access.expired, revoke.
Hosts
| Env | API base |
|---|---|
| Production | https://api.elknz.com |
| Local | https://api.elknz.com or http://127.0.0.1:1233 |
All paths below are under {API_BASE}/api/access/....
1) Webhooks (primary)
Headers
| Header | Meaning | ||
|---|---|---|---|
Content-Type | application/json | ||
X-Elknz-Event | access.paid \ | access.renewed \ | access.expired |
X-Elknz-Timestamp | Unix seconds when signed | ||
X-Elknz-Signature | sha256= + hex HMAC-SHA256 of raw body using partner_api_secret |
Body (example)
{
"event": "access.paid",
"event_id": "access.paid:ACC-…:…",
"status": "paid",
"purchase_number": "ACC-…",
"access_key": "elk_…",
"listing_id": 1,
"external_ref": "sku_or_plan",
"billing_mode": "one_time",
"interval": null,
"amount": 9.99,
"currency": "USD",
"elknz_user_id": 42,
"elknz_username": "buyer1",
"period_start": "…",
"period_end": null,
"paid_at": "…"
}Verify signature before trusting the body. Prefer unlocking from elknz_user_id + external_ref (ignore key paste when possible).
2) Verify entitlement (no key)
POST /api/access/verify-entitlement
X-Elknz-Access-Secret: aks_…
Content-Type: application/json
{
"external_ref": "sku_or_plan",
"elknz_user_id": 42
}You may send elknz_username instead of (or with) elknz_user_id. Optional listing_id if the same external_ref is reused.
Response:
{
"valid": true,
"purchase_number": "ACC-…",
"listing_id": 1,
"external_ref": "sku_or_plan",
"billing_mode": "recurring",
"interval": "month",
"status": "active",
"period_end": "…",
"elknz_user_id": 42,
"amount_paid": 9.99,
"currency": "USD"
}When invalid: valid: false + reason (unknown_listing, unknown_buyer, no_purchase, expired, period_ended, …).
3) Claim exchange (optional)
If listing has claim_url, after pay/renew the buyer is redirected to:
{claim_url}?claim=clm_…
Your backend:
POST /api/access/claim
X-Elknz-Access-Secret: aks_…
Content-Type: application/json
{ "claim": "clm_…" }Same entitlement response shape as verify. Claim tokens are short-lived (~10 minutes) and one-time.
4) Verify key (fallback)
POST /api/access/verify-key
X-Elknz-Access-Secret: aks_…
Content-Type: application/json
{ "access_key": "elk_…" }Required when the listing has a partner secret. Same response shape.
Mode A vs Mode B
| Access Mode B | Wallet Mode A | |
|---|---|---|
| Checkout | On ELKNZ catalog | On your site |
| Recurring today | Yes (Access renew) | Yes (subscriptions) |
| Money | Debit buyer → seller hold | Debit buyer → merchant wallet |
| Unlock | Webhook / entitlement / key / claim | Your payment.succeeded webhook |
Do not merge the two products. Use Access when the listing lives on ELKNZ; Mode A when checkout must live on your domain.