Help center/Your account

API keys, webhooks and calendar feeds

Getting your schedule into something else.

For owners, admins and schedulers

Read the transcript

This video shows how to get your schedule out of MedAligna and into everything else: a personal calendar feed for anyone on the team, API keys for your own systems, and signed webhooks that tell your server the moment something changes. Anyone on the team can do this, from My shifts. Scroll to Calendar sync and press Create calendar link. Now subscribe. Add to calendar opens your phone's own subscribe screen, for Apple Calendar or Outlook. Add to Google Calendar does the same for Google. Or copy the address into any calendar app. Published shifts appear in the phone's own timezone and stay in step, never more than five minutes behind. The feed carries only what a calendar needs: when, the shift type, the role and the site. No colleagues, no phone numbers, no pay. It covers published shifts from sixty days back to a hundred and twenty days ahead. Drafts and cancelled shifts are never in it. There's no login on a calendar feed, so the address itself is the secret. If it leaks, press Issue a new link: the old one stops working instantly. Turn off revokes it altogether. API keys and webhooks are on the Enterprise plan, and included in every trial. The screen is for owners and admins only, because a key authenticates your whole organization. Give the key a name that says what will hold it, like HR sync or Power BI, so that a year from now you know what breaks if you revoke it. Press Create key. Here's the key, and this is the only time it's shown. We store a fingerprint of it, not the key, so nothing can print it again. Copy it into the system that will use it, and send it as a bearer token in the Authorization header, never in a URL. If a key is ever lost or leaked, press Revoke. It stops on the very next request, with no cache to wait for, and you simply create another. Each key is limited to six hundred requests a minute. The reference is right on this screen. A GET request to /api/v1 confirms a key works and lists everything it can call: locations with their timezones, staff, assignments with real elapsed hours, credentials with their status worked out when you read them, open shifts, and the on-call chain. A key can only ever read its own organization. No endpoint takes a tenant parameter, so it can't be pointed anywhere else. Every timestamp is in UTC, every list takes limit and offset, and no endpoint returns pay rates or labour cost. Version 1 is read-only on purpose: every schedule change is made by a person, under a lock that re-checks the rules, and the API reports it. To be told the moment something happens, add a webhook endpoint. Type an https address, and tick the events it should receive, here shift assigned and schedule published. Tick none to receive all seven. Press Add endpoint. Each endpoint has its own signing secret. Show it, and paste it into your receiver. Every delivery carries an HMAC signature of the raw body, in the x-medaligna-signature header. The sample code shows how to verify it: compare the signature in constant time, check the created time is within five minutes, and keep the IDs you've already handled, because delivery is at least once. If your server answers with anything but a success, the delivery is retried after one minute, then four, sixteen and sixty-four minutes, then about four hours. After six attempts it's marked failed, and every attempt stays visible in the delivery list with its status code. An endpoint is never switched off for you: Pause and Resume are yours, and resuming retries whatever is still queued. That's getting your schedule out of MedAligna. A private calendar link for anyone on the team, read-only API keys shown exactly once, and signed webhooks that are retried and logged. Revoke a key or issue a new calendar link whenever one might have leaked.

Filmed in the product on October 24, 2026. All video tutorials

Calendar feeds

Any staff member can create a personal calendar link from My shifts, under Calendar sync, and subscribe to it in Apple Calendar, Google Calendar or Outlook. Their published shifts then appear in the phone's own timezone and stay in step as the schedule changes. Calendar apps refresh on their own cadence, and the feed is never more than five minutes behind.

The feed carries only what a calendar event needs: when, the shift type, the role and the site. No colleagues, no phone numbers, no pay. It shows published shifts from 60 days ago to 120 days ahead; drafts, cancelled and swapped-out assignments are never in it.

The address is the secret. There is no login on a calendar feed, so anyone holding the link can see those shifts. 'Issue a new link' kills the old one instantly; 'Turn off' revokes it. A revoked or mistyped link answers 404, and a valid link with a quiet fortnight answers an empty calendar, not an error.

Creating an API key

API keys and webhooks are on the Enterprise plan and included in every trial. The screen is kept to owners and admins: a key authenticates your whole organization to everything else you run, so it stays with whoever is accountable for it, not with everyone who can build a rota.

A key looks like `ms_live_…` and is shown exactly once, when it is created. We store a SHA-256 fingerprint, not the key, so nothing can print it again. If it is lost, revoke it and mint another. A revoked key stops on the very next request; there is no cache to wait for. Each key is limited to 600 requests a minute, reported in X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset headers.

  1. Open API keys as an owner or admin.
  2. Give the key a name that says what will hold it, such as 'HR sync', 'Power BI'.
  3. Copy the key from the confirmation. It is not shown again.
  4. Send it as `Authorization: Bearer ms_live_…`; `GET /api/v1` confirms it works and lists everything it can call.

What the API returns

A key authenticates your organization and can only ever read your organization. There is no parameter on any endpoint that names a tenant, so a key cannot be pointed anywhere else even by mistake; a bad or revoked key resolves to nothing, never to somebody else's data.

Version 1 is read-only. It serves locations (with each one's timezone), staff and one staff record, assignments with real elapsed hours (filtered by location and by `from`/`to` as instants, the same instants payroll exports), credentials with their status worked out at read time, open shifts with the slots remaining, and the on-call chain. Every timestamp is ISO-8601 in UTC; every list takes `limit` (1–200, default 50) and `offset`. No endpoint returns a pay rate, a bill rate or a labour cost.

There are no write endpoints, and that is deliberate. Every change to a schedule is decided under a database lock by a function that re-checks the rules and records the person who acted; an organization's key is not a person. Scheduling changes happen in the app, and the API reports them.

Webhooks

Add an endpoint (an https URL) and choose which events it receives, or none to receive all of them. Seven event types exist: shift.claimed, shift.assigned, shift.unassigned, schedule.published, swap.approved, oncall_board.published and oncall_board.unpublished. Each fires from the same transaction as the change it describes, so an event can never describe an assignment the database went on to refuse.

Every delivery is signed. Each endpoint has its own signing secret, shown on the API keys screen so you can paste it into your receiver, and the header `x-medaligna-signature` carries a hex HMAC-SHA256 of the raw request body. Verify it in constant time, check that `created` is within five minutes, and keep a record of the `id` you have already handled. The body is `{ id, type, created, org_id, data: { entity, entity_id, attributes } }`, with ids rather than names, because an integration looks the id up anyway.

Delivery is at least once: a receiver that answers anything other than a 2xx is retried after 1 minute, then 4, 16 and 64 minutes, then about 4 hours (six attempts in all), after which the delivery is marked failed and left visible in the delivery list with its status code and error. An endpoint is never switched off automatically; the screen shows its consecutive failures, and you can pause it and resume it, which clears the counter and retries whatever is still queued.

In the app this lives at /app/api-keys.

More from the help center

Not what you needed? Email helen@medicalstaffscheduling.com.

Already a customer? Sign in. Not yet? Open the live demo or start a free trial.