Rota API and webhooks
For connecting payroll, a till or another system to EstimateIt Rota. Back to Rota set-up
Tokens
A manager makes a token under Set-up, API tokens, choosing what it can do:
people:read: read everyone who isn't archivedpeople:write: add people, or change themshifts:read: read the shifts staff have been senthours:read: read agreed hours with pay, as on the payroll CSV
The token is shown once. Rota keeps only a hash of it, so a lost token can't be shown again: revoke it and make another. Send it with every call:
Authorization: Bearer rt_...
Each token can make 60 calls a minute. Every call, allowed or refused, goes in the business's activity log.
Calls
Everything is JSON. Dates are YYYY-MM-DD, times are 24-hour HH:MM, and money is in pence.
| Call | Scope | What it does |
|---|---|---|
GET rota-api.php?r=people | people:read | Returns {people: [...]}. |
POST rota-api.php?r=people | people:write | Send {"person": {...}} with the fields of the People form (first, last, email, ref, dob, contract, venues, skills and so on). With an id, that person is changed. Returns {ok, person, warn}. |
GET rota-api.php?r=shifts&from=&to= | shifts:read | The shifts as staff were last sent them, each with its person, venue, section and status (sent, offered, accepted or confirmed). |
GET rota-api.php?r=hours&from=&to= | hours:read | Agreed shifts with paid minutes, rate and pay, and total: {minutes, pay}. Up to 93 days at a time. |
Errors come back as {error, field?} with status 400 (a bad request), 401 (no token, a wrong one or a revoked one), 403 (the token hasn't that scope), 404 (no such call) or 429 (too many calls).
Webhooks
A manager adds a webhook under Set-up, Webhooks: an https:// address, and when to send. Rota posts JSON to it:
week.sent: the rota for a venue's week is sent, with every shift in itshift.agreed: someone accepts a shift, or a manager marks it confirmedping: the Send a test button
The body is {id, event, business, at, data}. Each post has these headers:
X-Rota-Event: the eventX-Rota-Delivery: the delivery's id, the same on every try, so a receiver can ignore one it has already seenX-Rota-Signature: t=<Unix time>,v1=<signature>
Checking the signature
The signature is the hex HMAC-SHA256 of t, a full stop and the raw body, keyed with the webhook's signing secret (shown once, when the webhook is added). Work it out yourself, compare it in constant time, and refuse a t more than 5 minutes from now, so an old post can't be sent again. In PHP:
$body = file_get_contents('php://input');
preg_match('/^t=(\d+),v1=([a-f0-9]{64})$/', $_SERVER['HTTP_X_ROTA_SIGNATURE'] ?? '', $m) || exit(http_response_code(400));
$ok = abs(time() - (int) $m[1]) <= 300 && hash_equals(hash_hmac('sha256', $m[1] . '.' . $body, $secret), $m[2]);
Retries
Answer with any 2xx status within 5 seconds. Anything else is tried again after 1, 5, 30, 120 and 720 minutes, then given up, which goes in the activity log. Redirects aren't followed.
Hours for payroll (CSV)
Under Set-up, Hours for payroll, choose the first and last day and download the CSV. Its columns: date, employee_ref, first_name, last_name, venue, section, start, end, break_minutes, paid_hours, hourly_rate, pay, status, grade, spinal_point (the last two, from 1.25.0, say which pay scale point the rate came from, and are empty for someone with their own hourly rate), then a Total row. Only shifts people agreed to are in it: sent and not still waiting for an answer.
Back to EstimateIt · Cookie settings · Accessibility · EstimateIt is an independent tool and is not affiliated with Atlassian or Jira. · Version 1.25.0