TerraGo API

Auth

Authentication and session lifecycle. Covers login (v1, plus the v2 staff zone/location-selection flow), zone/location selection for staff, JWT refresh-token rotation, logout, the password-reset email/reset pair, and the /auth/me bootstrap that returns the current user with their role, assigned zone/location, the registry context and onboarding status. All authenticated endpoints elsewhere expect the bearer access_token issued here.

8 endpoint(s)
POST Login V1 {{url}}/auth/access-token

Authenticate a user with email + password and receive a bearer access token plus a refresh token. This is the original (v1) login used by the web dashboard and non-staff clients.

Request Body

  • email (string, required): The user's email address (case-insensitive).
  • password (string, required): The user's password.
  • role_id (string UUID, optional): Role to authenticate as. Optional for System Admins; useful when an account maps to a single role.
  • remember_me (boolean, optional, default false): When true, the access token lives 7 days (10080 min) instead of the default TTL.

Response

Returns accesstoken, refreshtoken, tokentype (bearer), and expiresin (minutes).

Notes

  • The account must exist and be active (is_active = true) — deactivated accounts get a 401 with "Your account has been deactivated".
  • Every successful login rotates the refresh token: any previously issued refresh tokens for the user are deleted and a new 30-day refresh token is created.
  • Wrong email or password returns 401 Unauthorized.
Auth
Bearer token (inherited)
Request Body
{
    "email": "yamofaith@gmail.com",
    "password": "Terra@2025",
    "role_id": "989d4025-e939-41f7-b032-356c7269612c"
}
// {
//     "email" : "muriukicollins@gmail.com",
//     "password": "Terra2012.",
//     "role_id": "184ad925-a873-445e-a140-1edc1b11c2db"//optional if System Admin
// }
// {
//     "email":"developermike@gmail.com",
//     "password":"Terra@2012",
//     "role_id":"4583792c-7951-4bf5-ba5f-68c374a12420"
// }
// {
//     "email":"petekim211@gmail.com",
//     "password":"Terra@2012",
//     "role_id":"989d4025-e939-41f7-b032-356c7269612c"
// }
// {
//     "email":"faithyamo@terrasofthq.com",
//     "password":"Terrago@2025",
//     "role_id":"4583792c-7951-4bf5-ba5f-68c374a12420"
// }
// {
//     "email": "achiengyamo98@gmail.com",
//     "password": "Terra@2025",
//     "role_id": "6d0f4812-c376-47bb-b3db-ab23a0b8b2d0"
// }
Sample Response (200 OK)
{
    "status": 200,
    "data": {
        "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vMTI3LjAuMC4xOjgwMDAvYXBpL2F1dGgvYWNjZXNzLXRva2VuIiwiaWF0IjoxNzc4NDkzMTE2LCJleHAiOjE3Nzg2NjU5MTYsIm5iZiI6MTc3ODQ5MzExNiwianRpIjoiWml0bmJyVDBoSURMQ1pSRyIsInN1YiI6IjEzMiIsInBydiI6IjIzYmQ1Yzg5NDlmNjAwYWRiMzllNzAxYzQwMDg3MmRiN2E1OTc2ZjciLCJyb2xlIjoiU3RhZmYiLCJyb2xlX2lkIjoiOTg5ZDQwMjUtZTkzOS00MWY3LWIwMzItMzU2YzcyNjk2MTJjIn0.AogSE1RgTpEDEX4WYU7M4Ao8Li1bjwxRxBsMEXgnM10",
        "refresh_token": "dBQb7TI6wr3DsrjwTI8ZwEzokpxsDbGcsJYAJpPcB8EN6pEVjjJmKeitE6FC6KFp",
        "token_type": "bearer",
        "expires_in": 2880
    },
    "message": "Token Refreshed Successfully"
}
POST Login V2 (Staff Zone/Location-Selection Flow) {{url}}/auth/access-token/v2

Authenticate a user via the v2 login flow. Unlike v1, this endpoint requires a client type and treats Staff users (drivers, bus minders, security) differently from other roles: Staff must finish authentication with a second call to Select Zone/Location before they get a usable access token.

Request Body

  • email (string, required): The user's email address.
  • password (string, required): The user's password.
  • client (string, required): Either app or web. Staff accounts may only log in with client=app; non-Staff accounts may only use client=web.
  • remember_me (boolean, optional, default false): Extends the token lifetime (1440 minutes normally, 10080 minutes / 7 days if true).

Response

  • Staff (client=app): Returns a short-lived temptoken (not a usable access token yet) plus the staff's assigned zones/locations. Pass temptoken and the chosen zone/location UUID to Select Zone/Location to get a real access_token.
  • Everyone else: Returns accesstoken, refreshtoken, tokentype, and expiresin directly, same shape as Login V1.

Notes

  • The account must be active (is_active = true).
  • Any previous refresh tokens for the user are invalidated on login.
Auth
Bearer token (inherited)
Request Body
{
    "email": "yamofaith@gmail.com",
    "password": "Terra@2025",
    "client": "app" // Required for terrago app only to allow select of zone
}
Sample Response (200 OK)
{
    "status": 200,
    "data": {
        "temp_token": "0PHPFgj1OqZQAjT3RY1V2h5eMWW8Yl3floD8zbDjxiXkGNmNL33wmnSfm2CpYXAh",
        "staff": {
            "id": "818e3ea7-543b-4739-9567-7a5a3e29e6c7",
            "name": "Test Driver",
            "email": "yamofaith@gmail.com",
            "phone": "+254765432144"
        },
        "zones": [
            {
                "id": "94e511b2-9a5f-45d2-ac5b-a53d356df6fb",
                "name": "Y Zone",
                "metadata": null
            },
            {
                "id": "b6b4c801-55ec-4b09-a894-e92794ceec2f",
                "name": "Test Zone",
                "metadata": null
            }
        ]
    },
    "message": "Select an assigned zone to continue"
}
POST Select Zone/Location {{url}}/auth/select-zone

Second step of the Staff login flow. Exchanges the temp_token returned by Login V2 plus a chosen zone/location for a full, zone/location-scoped access token. Only used for Staff accounts (drivers, bus minders, security) who select which zone/location/vehicle they're operating for the session.

Request Body

  • temp_token (string, required): The temporary token returned by POST /auth/access-token/v2.
  • waaszoneuuid (string, required): UUID of the zone/location the staff member is selecting. Must be one of the zones/locations assigned to them.
  • remember_me (boolean, optional): Extends the session from 30 days to 90 days.

Response

Returns accesstoken, refreshtoken, tokentype, expiresin — use access_token as the Bearer token for all subsequent authenticated requests.

Notes

  • The temp_token is single-use and stored server-side (Redis) with a 10 minute TTL; it is deleted once redeemed.
  • Fails if the temp token has expired or if the staff member doesn't have access to the given zone/location.
Auth
None
Request Body
{
    "waas_zone_uuid": "825e7402-a072-4926-9bfb-27280c2be5eb",
    "remember_me": false, //optional
    "temp_token": "wVeqNnVP4qRACCN4bzUC60VQRFwTtTWvAcPZxINokgIwA9NC7DXpkDMlU81zLjyz"
}
Sample Response (200 OK)
{
    "status": 200,
    "data": {
        "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vMTI3LjAuMC4xOjgwMDAvYXBpL2F1dGgvc2VsZWN0LXpvbmUiLCJpYXQiOjE3Nzg0OTA2MjgsImV4cCI6MTc3ODY2MzQyOCwibmJmIjoxNzc4NDkwNjI4LCJqdGkiOiJmMG41TzdtTHR6TXdMc1ZaIiwic3ViIjoiMTMyIiwicHJ2IjoiMjNiZDVjODk0OWY2MDBhZGIzOWU3MDFjNDAwODcyZGI3YTU5NzZmNyIsInJvbGUiOiJTdGFmZiIsInJvbGVfaWQiOiI5ODlkNDAyNS1lOTM5LTQxZjctYjAzMi0zNTZjNzI2OTYxMmMifQ.-lugNxsQDl7eqmRCnOnVlZLGLt6-5u5bGU5YQaUNDkM",
        "refresh_token": "1edGYkABGaDlKTsx3I8NSgNHvR5WzorxLxk7WapBzlt2u4r8N9QFa7mZRGyNfBTS",
        "token_type": "bearer",
        "expires_in": 2880
    },
    "message": "Access token generated successfully"
}
PUT Refresh Token {{url}}/auth/refresh

Exchange a valid, unexpired refresh token for a new access token and a new refresh token, so a session can continue without the user re-entering credentials.

Request Body

  • refresh_token (string, required): The refresh token issued at login (or by a previous refresh).

Response

Returns a fresh accesstoken, a new refreshtoken, and expires_in (seconds).

Notes

  • Refresh tokens are single-use and rotated: the presented token is deleted and replaced with a new 30-day token on every call. Store the returned refresh_token for the next refresh.
  • If the token is missing, expired, or already used, the endpoint returns 401 Unauthorized ("Refresh token expired or invalid") and the user must log in again.
  • For Staff sessions, the refresh preserves the selected-zone/location context (session_key) so the new access token stays scoped to the same zone/location.
  • No bearer token is required to call this — the refresh token itself is the credential.
Auth
Bearer token
Request Body
{
    "refresh_token" : "ShqMCIEu95RW3UrJPlkDahAiwxqf5oYFtaEyroyNrVD8ApU2mvnOuRa1XkVAqWb3"  // The refresh token issued at login
}
Sample Response (200 OK)
{
    "status": 200,
    "data": {
        "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3RlcnJhZ29zdGcudGVycmFzb2Z0aHEuY29tL2FwaS9hdXRoL3JlZnJlc2giLCJpYXQiOjE3Njk1OTk2MDksImV4cCI6MTc2OTYwMzIwOSwibmJmIjoxNzY5NTk5NjA5LCJqdGkiOiJ0QWk0c0IxbjFXdVVYOGxPIiwic3ViIjoiNDMiLCJwcnYiOiIyM2JkNWM4OTQ5ZjYwMGFkYjM5ZTcwMWM0MDA4NzJkYjdhNTk3NmY3Iiwicm9sZSI6IkFkbWluaXN0cmF0aXZlIFN0YWZmIiwicm9sZV9pZCI6IjQ1ODM3OTJjLTc5NTEtNGJmNS1iYTVmLTY4YzM3NGExMjQyMCJ9.RsmjkbmFdIgXASVr2_AJTI-4b02woi0TxpOzow1vxaQ",
        "refresh_token": "O50H7TPiRRIEArX3EFog075dg33X6BDBKz9lvV8jYxLWt99DN9gOheOcnmSzWCy6",
        "expires_in": 3600
    },
    "message": "Token refreshed"
}
PUT Logout {{url}}/auth/logout

Log out the currently authenticated user. Invalidates the current access token (JWT) and deletes all of the user's refresh tokens, so neither the access token nor any refresh token can be used again.

Notes

  • Requires a valid bearer token (auth:api).
  • After logout, the client should discard both the access and refresh tokens; continuing to use them returns 401 Unauthorized.
  • Idempotent from the client's perspective — calling it again after logout simply fails auth.
Auth
Bearer token
Sample Response (200 OK)
{
    "status": 200,
    "data": [],
    "message": "Successfully logged out"
}
POST Send Reset Password Email {{url}}/auth/password/email

Sends a password reset email to the specified user.

Required parameters:

  • email (string): The user's email address to send the reset link to.
  • url (string): The URL to which the user will be redirected to reset their password.

Expected behavior: If the email exists in the system, a password reset link will be sent to the provided email address. The response does not reveal whether the email exists for security reasons.

Response

Empty data; message confirms a reset link was sent. For security it does not reveal whether the email is registered.

Auth
Bearer token (inherited)
Request Body
{
    "email" : "alex.kimani@example.com",
    "url": "https://terragoui.terrasofthq.com/reset-password"
}
Sample Response (200 OK)
{
    "status": 200,
    "data": [],
    "message": "Password reset link sent successfully"
}
POST PasswordReset {{url}}/auth/password/reset

Resets a user's password by accepting the user's email, new password, password confirmation, and a valid password reset token. All fields are required in the request body:

  • email: The user's registered email address
  • password: The new password to set
  • password_confirmation: Must match the new password
  • token: The password reset token provided to the user

On success, the user's password is updated and a confirmation response is returned. Use this endpoint after initiating a password reset process.

Response

Empty data; message confirms the password was updated. A validation error is returned if the token/email is invalid or the passwords don't match.

Auth
Bearer token (inherited)
Request Body
{
    "email" : "alex.kimani@example.com",  // User's email address
    "password": "Terra@2012.",  // User's password
    "password_confirmation": "Terra@2012.",  // Repeat of the new password (must match)
    "token": "036d3679316643feb280c6fc2161fbd7c325693a5083c5e86946f731a7581061"  // Password-reset token from the email link
}
Sample Response (200 OK)
{
    "status": 200,
    "data": [],
    "message": "Password reset successfully"
}
GET me {{url}}/auth/me

Return the full profile of the currently authenticated user, enriched with the context the app needs on startup. This is the primary "who am I / bootstrap" call after login.

Response includes

  • The user's core profile (via UserResource), with role and supervisor loaded.
  • Assigned zone/location — for Staff, the the registry zone/location selected for the active session (resolved from the session key).
  • the registry beneficiary context — the linked the registry account's beneficiaryappfilters and tags (keyed by beneficiary id), used to drive route/student filtering.
  • Setup status — for a school admin (Administrative Staff), a freshly computed onboarding checklist (location, zones/locations, routes, trips, staff, parents) is calculated and cached on the user.
  • Pending tasks — e.g. an in-progress (ACTIVE) trip for the user, so the app can resume it.

Notes

  • Requires a valid bearer token (auth:api).
  • Returns a warning if the registry is unreachable, since parts of the payload depend on it.
Auth
Bearer token
Sample Response (200 OK)
{
    "data": {
        "id": "68b86410-e6e8-4b5f-9a3d-8265a7773c0e",
        "first_name": "Jane",
        "middle_name": "Wanjiku",
        "last_name": "Otieno",
        "phone": "+254711223344",
        "email": "jane.otieno@example.com",
        "identification_document": "passport",
        "identification_number": "A1234567",
        "dob": "1995-08-15 00:00:00",
        "gender": "Female",
        "third_party_id": "eecc4c6b-32c8-4efb-b312-b3d1dac2c4f5",
        "is_active": true,
        "role": "Administrative Staff",
        "metadata": null,
        "image": null,
        "notes": null,
        "created_at": "2025-12-05 10:51:21",
        "filters": {
            "account": [],
            "dependant": [
                {
                    "id": "7b18d5ea-346e-4b5c-8936-4a1f4cdaabb0",
                    "name": "Universal Tag",
                    "created_at": "2025-05-21T12:04:02.000000Z"
                },
                {
                    "id": "f2c5edd9-f2f1-404e-ba80-44800cb37bc6",
                    "name": "ATHI RIVER PRIMARY SCHOOL",
                    "created_at": "2024-04-12T13:23:20.000000Z"
                },
                {
                    "id": "5f9cbe4d-8274-47f4-84cc-8ba83f247c1e",
                    "name": "WS3",
                    "created_at": "2025-05-21T12:04:48.000000Z"
                }
            ],
            "iot": [],
            "wallet": [],
            "zone": []
        }
    },
    "status": 200,
    "message": "User Retrieved Successfully"
}