Server events and signed requests

Last updated 7 Oct 2026

Your site's server sends events to https://ingest.onepanelforall.com, signed with the site's secret. Use it from any language; a ready .NET package (OnePanelForAll.Client) does it for you.

Endpoints

Method Path Purpose
POST /api/v1/ingest/events send 1–100 events
GET /api/v1/ingest/ping check the key, the secret and the clock

Signing

Every request carries four headers:

Header Value
X-OnePanel-Key the site's key id, opk_…
X-OnePanel-Timestamp Unix time in seconds (at most 5 minutes off)
X-OnePanel-Nonce 16–64 characters [A-Za-z0-9_-], new for every request
X-OnePanel-Signature v1= + lower-case hex HMAC
canonical = "v1\n" + timestamp + "\n" + nonce + "\n" + METHOD + "\n" + path + "\n" + hex(sha256(body))
signature = "v1=" + hex(HMAC-SHA256(secret, canonical))

path has no query string; body is the exact bytes sent (empty for GET). Test vector: secret ops_test-secret, timestamp 1700000000, nonce nonce-0123456789ab, POST /api/v1/ingest/events, body {"events":[]} give v1=c1cc9d2a7b5ad84585991ae4d740cf3b84378abd27ce15a0ff344aae0e0c9809.

Body

{ "events": [ {
    "id": "contact-8f14e45f",
    "type": "contact_message",
    "version": 1,
    "occurredAt": "2026-10-03T18:35:00Z",
    "data": { "name": "Ana Pop", "email": "[email protected]", "message": "Hello…" }
} ] }

Give every event an id from your own data: sending the same id again is safe, it is stored once.

Type Main fields in data
contact_message name, email, subject, message, pageUrl
user_signup userId, email, name
user_deleted userId
payment_succeeded, payment_failed, payment_refunded paymentId, amount, currency, plan, reason
subscription_canceled subscriptionId, plan, reason
order_placed orderId, amount, currency, email, name
custom_event name, properties (≤ 20)

Answers

200 with { "accepted": 1, "duplicates": 0, "rejected": [] }; a bad event is rejected alone. 401 means a wrong key, secret or clock; retry 409, 429 and 5xx later with a new nonce.

.NET

builder.Services.AddOnePanel(builder.Configuration.GetSection("OnePanel"));

await onePanel.SendAsync(OnePanelEvent.ContactMessage(
    message: form.Message, name: form.Name, email: form.Email, id: $"contact-{saved.Id}"));
onePanel.Enqueue(OnePanelEvent.UserSignup(user.Id.ToString(), user.Email, user.Name));

Settings, as environment variables on your server: OnePanel__BaseUrl, OnePanel__KeyId, OnePanel__Secret. Never put the secret in your code or repository.