Launch (signing a user in)
Your ERP is the identity provider. TimetableMaster never stores or checks a password for your users, and never shows them a login screen.
The flow
1. User clicks "Timetable" in your product
2. Your BACKEND calls POST /api/partner/v1/auth/token (API key, server-to-server)
3. You redirect the user's browser to the returned launchUrl
4. We set a session cookie and drop them into the timetable UI
The token you get back is single-use and expires in 60 seconds. It has to travel through a
browser, and URLs leak into history, Referer headers and proxy logs. A short single-use token
means a leaked launch URL is worthless almost immediately. Mint one per click; never cache them.
Mint a token
POST /api/partner/v1/auth/token
Authorization: Bearer ttm_<your api key>
Content-Type: application/json
{
"externalUserId": "EMP-1001",
"name": "Edna Krabappel",
"email": "edna@northwood.example",
"shortName": "EK",
"role": "Registrar"
}
| Field | Required | Notes |
|---|---|---|
externalUserId | Yes | Your opaque id for this user. This is the identity we key on |
name | On first launch | Required only when we have not seen this externalUserId before |
email | No | Links a login account. Omit for users who only need to be scheduled |
shortName | No | Used in compact timetable views |
role | No | Your role name; mapped to ours per organisation (see below) |
Response:
{
"success": true,
"data": {
"token": "…",
"launchUrl": "https://api.timetablemaster.com/launch?token=…",
"expiresIn": 60,
"userCreated": true
}
}
Then 302 the browser to launchUrl.
Users are created automatically
The first time an externalUserId arrives, we create the user. Every later launch reuses it. You
never pre-provision anyone.
Two behaviours worth knowing:
Identity is externalUserId, never email. Matching on email would let anyone holding the API
key bind a launch onto an existing account by claiming its address. Emails are stored as a contact
detail, not as identity.
Names must be unique within an organisation. If two people share a name, the second is created as
"John Smith (EMP-2002)" and the response includes renamedTo so you can reconcile. We never
merge two of your users into one of ours. That would fuse their timetables.
A launch never renames an existing user. Name changes belong to entity sync.
Role mapping
Send your own role name in role. We map it per organisation, configured during onboarding:
"Registrar" → admin
"Faculty" → member
Anything unmapped falls back to the organisation's default role, so a new role on your side can
never silently grant elevated access. owner is not assertable: it carries ownership-transfer
semantics and cannot be assigned from a payload.
Logout
Hitting logout clears the session and returns a returnUrl pointing back into your product. We
never render a login page for a partner user. Configure the URL during onboarding.
Errors
| Code | Status | Meaning |
|---|---|---|
EXTERNAL_USER_ID_REQUIRED | 400 | externalUserId missing or blank |
NAME_REQUIRED | 400 | First launch for this user, and no name was supplied |
NAME_COLLISION | 409 | The name and its disambiguated form are both taken |
MEMBER_INACTIVE | 403 | The user is archived in TimetableMaster |
PARTNER_ACCESS_DISABLED | 403 | Partner access is not enabled for this organisation |
INVALID_LAUNCH_TOKEN | 401 | Already used, expired, or never existed |
Access is re-checked when the token is redeemed, not only when it is minted. Revoking access invalidates tokens already in flight.