Get started
Getting started
From access to your first webhook in five minutes: request a token, make your first call, create a destination and trigger a test alert in the sandbox.
On this page
This guide goes from access to your first received alert, all in the sandbox. You need a terminal with curl and, for step 5, a public https URL where you can receive webhooks.
The examples read the credentials from environment variables. Don’t write them in the code.
export SAFEONUBA_CLIENT_ID="example-client"
export SAFEONUBA_CLIENT_SECRET="cs_…"1. Request access
We register access ourselves, customer by customer, and the reason is recorded. The plant sees in its dashboard (Settings → Integrations) who has access, to what and why.
When you are registered you receive a client_id and a client_secret, which starts with cs_. The secret is shown only once: store it in your secrets manager at that moment.
To request it, write to us at info@safeonuba.com with your company, the plant and what you want to integrate.
2. Request a token
The token is requested with OAuth2 client_credentials and lasts one hour.
curl -X POST https://sandbox.api.safeonuba.com/v1/oauth/token \
-d grant_type=client_credentials \
-d client_id="$SAFEONUBA_CLIENT_ID" \
-d client_secret="$SAFEONUBA_CLIENT_SECRET"const res = await fetch('https://sandbox.api.safeonuba.com/v1/oauth/token', {
method: 'POST',
body: new URLSearchParams({
grant_type: 'client_credentials',
client_id: process.env.SAFEONUBA_CLIENT_ID,
client_secret: process.env.SAFEONUBA_CLIENT_SECRET,
}),
});
const { access_token } = await res.json();import os
import requests
res = requests.post(
"https://sandbox.api.safeonuba.com/v1/oauth/token",
data={
"grant_type": "client_credentials",
"client_id": os.environ["SAFEONUBA_CLIENT_ID"],
"client_secret": os.environ["SAFEONUBA_CLIENT_SECRET"],
},
timeout=10,
)
res.raise_for_status()
access_token = res.json()["access_token"]using System.Net.Http.Json;
using System.Text.Json;
using var http = new HttpClient();
var res = await http.PostAsync("https://sandbox.api.safeonuba.com/v1/oauth/token",
new FormUrlEncodedContent(new Dictionary<string, string>
{
["grant_type"] = "client_credentials",
["client_id"] = Environment.GetEnvironmentVariable("SAFEONUBA_CLIENT_ID")!,
["client_secret"] = Environment.GetEnvironmentVariable("SAFEONUBA_CLIENT_SECRET")!,
}));
res.EnsureSuccessStatusCode();
var token = (await res.Content.ReadFromJsonAsync<JsonElement>()).GetProperty("access_token").GetString();The response:
{
"access_token": "at_9c1e…",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "alerts:read alerts:write musters:read"
}Keep the access_token for the next steps:
export SAFEONUBA_TOKEN="…"3. Make your first call
GET /v1/sites returns the sites you have access to. Any scope will do, so it is the best way to check that the token works.
curl https://sandbox.api.safeonuba.com/v1/sites \
-H "Authorization: Bearer $SAFEONUBA_TOKEN"Note the id of your sandbox site: you will use it when you run a scenario.
4. Create a webhook destination
A destination is the URL of your receiver and the events you want it to get. It needs the webhooks:manage scope.
curl -X POST https://sandbox.api.safeonuba.com/v1/webhooks \
-H "Authorization: Bearer $SAFEONUBA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://controlroom.customer.example/safeonuba",
"event_types": ["alert.*", "muster.*"]
}'The response includes the signing secret, which starts with whsec_.
5. Receive and verify
Your receiver has to do three things with each delivery:
- Check the signature in
X-SafeOnuba-Signatureover the raw body. - Respond
2xxin under 5 seconds. - Process the event afterwards, outside that request.
Verifying a webhook signature has the complete receiver in Node, Python and C#. Once you have it deployed, check that something reaches it:
curl -X POST https://sandbox.api.safeonuba.com/v1/webhooks/DESTINATION_ID/test \
-H "Authorization: Bearer $SAFEONUBA_TOKEN"An alert.created arrives, marked simulated: true and signed like a real one.
6. Trigger a test SOS
In the sandbox, a scenario makes a simulated watch press the SOS. What you receive is the same as you would receive from a real watch.
curl -X POST https://sandbox.api.safeonuba.com/v1/sandbox/scenarios \
-H "Authorization: Bearer $SAFEONUBA_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "scenario": "sos" }'Your receiver gets an alert.created with the complete alert in data.alert. If nobody closes it, it closes itself after 10 minutes.
7. Acknowledge it from your control room
With the alerts:write scope, your control room can take charge of the alert. Always on behalf of a person: the actor is the operator who acknowledged it, and is recorded in the alert’s timeline.
curl -X PUT https://sandbox.api.safeonuba.com/v1/alerts/ALERT_ID \
-H "Authorization: Bearer $SAFEONUBA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"status": "acknowledged",
"actor": { "name": "E. Example", "external_id": "OP-117" }
}'Your receiver gets alert.acknowledged, and in the SafeOnuba dashboard the alert shows as acknowledged “via integration”.
Next steps
- Authentication and scopes: caching the token and rotating the secret without downtime.
- Webhooks: retries, duplicates, order and filters.
- Sandbox: the full evacuation scenario, from start to finish.