Acting user
Attribute a write to the staff member who made it, with X-Acting-User-Id.
Every write you send arrives at medos as somebody. Without X-Acting-User-Id that
somebody is the workspace administrator — so a month of prescriptions, status
changes and patient edits all read as one account in the audit trail.
Send the header and medos records the real staff member instead.
X-Acting-User-Id: 4821The value is a medos user id — the same id GET /v1/doctors and the staff
list return. Not your own system's user id, and not an email.
Where it is required
| Endpoint kind | Header | Without it |
|---|---|---|
| Reads | Optional | Attributed to the workspace administrator |
| Every write | Required | 400, naming x-acting-user-id |
Reads are optional on purpose: a nightly roster sync has no human actor, and requiring one would mean mapping a service account before you could read anything.
Writes are not optional. A clinical record whose author is unknown is worse than one you could not write.
{
"statusCode": 400,
"status": "failed",
"fieldErrors": [
{
"field": "x-acting-user-id",
"error": "required: name the staff member this write is attributed to, so medos records the real actor rather than the workspace admin"
}
]
}Mapping your staff to medos users
You need a stored mapping from each of your users to a medos user id. Build it once from the practitioner and staff lists, and keep it with your integration config rather than resolving it per request.
curl -sG "https://api.medos.one/v1/doctors" \
-H "x-api-key: $MEDOS_API_KEY"The id must belong to your workspace. One that does not is refused:
{
"statusCode": 403,
"status": "failed",
"message": "User 9912 is not an active member of this workspace."
}An id that is real but deactivated is refused the same way. If a staff member leaves, writes attributed to them start failing — which is the point.
A deactivation can take up to five minutes to bite
Membership is cached briefly. A user deactivated in medos may still be accepted as an actor for a few minutes. Medos still applies its own permission checks to them in that window, so this is an attribution lag, not a way around access control.
Permissions are medos's, not the gateway's
The gateway checks that the user you named is an active member of your workspace. It does not check whether that user is allowed to perform the action.
That check happens inside medos, against its own roles. So:
Sending a receptionist's id on a prescription write will be refused by medos, not by the gateway — with medos's own permission error, not a
400about the header.
If a write is rejected for reasons that look like role or permission, the fix is in the user's medos role, not in the request.
Two headers that are easy to confuse
| Header | Names | Used by |
|---|---|---|
X-Acting-User-Id | the staff member performing the action | every write on the back-office surface |
x-end-user-id | the patient the request is for | the OTP-gated booking and patient-search endpoints |
They are different subjects with different lifetimes, which is why they are different headers. Sending one where the other belongs will not work: the OTP gate scopes verification per patient, and attribution records a member of your staff.