Overview
Staaro's public integration point is an inbound webhook trigger. Your server, Zapier, Make or WooCommerce sends one signed HTTP POST after a customer event; Staaro validates it and queues one review-request SMS. Machine-facing JSON keys, headers, status values and CSV fields are always language-neutral.
POST https://api.staaro.ee/api/v1/triggers/webhook/YOUR_WEBHOOK_TOKENQuick start
- Open
/integrations/webhookin Staaro. - Copy the webhook URL and generate a signing secret.
- Create the JSON body, sign its exact raw bytes and send the request.
BODY='{"phone":"+37255555555","customer_name":"Mari Tamm","external_id":"order-1042"}'
SIGNATURE=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$STAARO_SECRET" -hex | sed 's/^.* //')
curl -X POST 'https://api.staaro.ee/api/v1/triggers/webhook/YOUR_WEBHOOK_TOKEN' \
-H 'Content-Type: application/json' \
-H "X-Staaro-Signature: $SIGNATURE" \
--data-binary "$BODY"Authentication
For the canonical Staaro payload, compute HMAC-SHA256 over the exact raw request body with your webhook secret and send the lowercase hexadecimal digest in X-Staaro-Signature. Never sign parsed or re-serialised JSON. WooCommerce's built-in webhook format is also accepted: its base64 HMAC-SHA256 value belongs in X-WC-Webhook-Signature.
The URL token identifies the organisation; it is not a substitute for the signature. Keep both values in server-side secrets. Rotating the signing secret immediately invalidates the old one.
Canonical request body
{
"phone": "+37255555555",
"customer_name": "Mari Tamm",
"external_id": "order-1042",
"scheduled_send_at": "2026-08-05T10:00:00Z",
"language": "en",
"template_vars": {"location": "Tallinn"}
}phone— required to send; free-form input is normalised to E.164 using the organisation country.customer_name— optional trace metadata.external_id— strongly recommended stable event ID for idempotency.scheduled_send_at— optional ISO 8601 time. Unsupported values fall back to the organisation delay.languageandtemplate_vars— retained metadata. The actual customer language is the organisation's saved messaging language and is snapshotted when queued.
Responses
A queued request returns 202 Accepted:
{
"received": true,
"sms_message_id": "3ef8…",
"scheduled_send_at": "2026-08-05T10:00:00"
}Expected, non-retryable business outcomes return 200 with askipped reason such as no_phone, opted_out,quota_exhausted, suspended orplan_requires_staaro. A duplicate returns{"received":true,"duplicate":true}.
401— missing or invalid signature.404— webhook token not recognised.400— malformed JSON or configuration that must be fixed.429— more than 60 requests per minute for the webhook organisation.
Idempotency
For canonical requests, Staaro scopes a supplied external_id to your webhook token. Reusing it does not queue a second SMS. Without one, Staaro hashes the raw body; even whitespace changes can then create a new event. WooCommerce uses the order ID and sends at most once per order. Cancelled, refunded or failed WooCommerce orders cancel a still-queued SMS.
Python example
import hashlib, hmac, json, requests
payload = {"phone": "+37255555555", "external_id": "order-1042"}
body = json.dumps(payload, separators=(",", ":")).encode()
signature = hmac.new(SECRET.encode(), body, hashlib.sha256).hexdigest()
response = requests.post(URL, data=body, headers={
"Content-Type": "application/json",
"X-Staaro-Signature": signature,
}, timeout=10)
response.raise_for_status()Limits, retries and security
- Use a 10-second HTTP timeout and retry only network failures, 429 and 5xx with exponential backoff.
- Do not retry a 200 skipped response or a 4xx configuration error.
- Store secrets outside source control and browser/mobile code; never log raw secrets, signatures or customer phone numbers.
- Rotate the secret immediately if exposure is suspected.
- Plan quota, account status, opt-outs and sender/review-link configuration are enforced server-side.
Integration support: staaro.eu@gmail.com.
LAST MODIFIED · 04/08/2026 · Staaro OÜ · 17561530