Business Signals EndPoint
Your website already knows how many users it has, who registered today, how many articles or profiles exist, how many payments went through and what is waiting in moderation. Send those numbers to one EndPoint and watch every site you run in a single dashboard — with anomaly alerts, targets and a portfolio benchmark. It is an EndPoint, not a widget: server-to-server, no personal data, just counts.
What you can send
Any counter you name. Group it into a category and we chart it, break it down and watch it for you.
Users
total users, registrations by day, subscribers, deletions
Content
materials by any type — articles, videos, profiles, listings
Revenue
payment attempts, successful payments, refunds — plus derived conversion
Moderation
profiles awaiting deletion, reported items, review queues
Feedback
contact-form messages, support tickets, NPS
Anything else
name a metric and it appears — no config on our side
The EndPoint
Examples
curl -X POST https://astrina.io/endpoint/ingest \
-H "X-Astrina-Key: YOUR_SITE_KEY" \
-H "Content-Type: application/json" \
-d '{
"signals": [
{ "metric": "users", "kind": "gauge", "value": 15230, "category": "users" },
{ "metric": "registrations", "value": 42, "category": "users" },
{ "metric": "materials", "kind": "gauge", "value": 842, "dim": "article", "category": "content" },
{ "metric": "materials", "kind": "gauge", "value": 301, "dim": "video", "category": "content" },
{ "metric": "payment_requests", "value": 18, "category": "revenue" },
{ "metric": "payment_success", "value": 11, "category": "revenue", "unit": "EUR" },
{ "metric": "feedback", "value": 3, "category": "feedback" },
{ "metric": "profiles_to_delete", "kind": "gauge", "value": 5, "category": "moderation",
"good_dir": "down", "attention": true }
]
}'<?php
// Run this daily (cron) on your own site. Sends only counts — never personal data.
$key = 'YOUR_SITE_KEY';
$payload = ['signals' => [
['metric' => 'users', 'kind' => 'gauge', 'value' => usersTotal(), 'category' => 'users'],
['metric' => 'registrations', 'value' => registrationsToday(), 'category' => 'users'],
['metric' => 'payment_requests', 'value' => paymentAttemptsToday(), 'category' => 'revenue'],
['metric' => 'payment_success', 'value' => paymentsPaidToday(), 'unit' => 'EUR', 'category' => 'revenue'],
['metric' => 'feedback', 'value' => feedbackToday(), 'category' => 'feedback'],
['metric' => 'profiles_to_delete', 'kind' => 'gauge', 'value' => deletionQueue(),
'category' => 'moderation', 'good_dir' => 'down', 'attention' => true],
]];
$ch = curl_init('https://astrina.io/endpoint/ingest');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['X-Astrina-Key: YOUR_SITE_KEY', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_RETURNTRANSFER => true,
]);
$resp = json_decode(curl_exec($ch), true);
// Two-way: act on anything Astrina asks for (e.g. a fresh full snapshot).
foreach ($resp['requests'] ?? [] as $cmd) {
if ($cmd['cmd'] === 'full_snapshot') { /* push your whole history, then: */ }
// acknowledge so it is not re-sent:
// curl https://astrina.io/endpoint/ack -d '{"id": ' . $cmd['id'] . '}'
}<?php
// One-off: backfill a year of daily registrations so the charts start full.
$signals = [];
foreach (registrationsByDay('-365 days') as $day => $n) { // 'YYYY-MM-DD' => int
$signals[] = ['metric' => 'registrations', 'value' => $n, 'day' => $day, 'category' => 'users'];
}
// up to 2000 points per request
foreach (array_chunk($signals, 2000) as $chunk) {
postJson('https://astrina.io/endpoint/ingest', ['signals' => $chunk], 'YOUR_SITE_KEY');
}# Pull this site's computed health BACK (current values, 30-day deltas, target
# progress, open alerts, and the median across YOUR OTHER sites) to show it in-app:
curl "https://astrina.io/endpoint/insights" -H "X-Astrina-Key: YOUR_SITE_KEY"Replace YOUR_SITE_KEY with the key from your dashboard. Each site has its own key; it only ever authorises pushing that one site’s numbers.
Signal fields
| Field | Meaning | |
|---|---|---|
metric | required | Any key you choose — users, registrations, materials, payment_success… Stored under this key forever. |
value | required | The number. For a gauge it is the current total; for a count it is that period's amount. |
kind | optional | "gauge" (a snapshot total, e.g. total users now) or "count" (per-day amount, the default). |
day | optional | YYYY-MM-DD. Defaults to today. Send past days to backfill; re-sending a day overwrites it. |
dim | optional | A breakdown value, e.g. the material type "article"/"video". One series per dimension. |
category | optional | users · content · revenue · moderation · feedback · engagement · custom — groups the metric. |
unit | optional | A short unit shown next to the number, e.g. "EUR", "GB". |
good_dir | optional | "up" (default), "down" (lower is better, e.g. a deletion queue) or "none". |
attention | optional | true pins the metric to the cross-site cockpit as a "needs clearing" number. |
event | optional | true + a count with no day increments today instead of overwriting it. |
Two-way by design
Commands back
Every push returns any commands you queued in the dashboard — e.g. “push a full snapshot”. Your site runs them and acks.
Insights back
Call /endpoint/insights to show your own live numbers, targets and alerts inside your admin panel.
Portfolio benchmark
We return the median of each metric across your other sites, so a site can show how it compares to the rest.
Anomaly watch
We watch for sharp drops, spikes, a silent integration and a payment funnel that stops converting — and flag them.
Business Signals EndPoint
What this page answers
- business Signals EndPoint
- business Signals EndPoint guide
- business Signals EndPoint explained
- business Signals EndPoint tutorial
- getting started with Business Signals EndPoint
- business Signals EndPoint best practices
- what is Business Signals EndPoint
- business Signals EndPoint for beginners
- business Signals EndPoint checklist
- business Signals EndPoint examples
- why Business Signals EndPoint matters