Reference

API Reference

The Servelo REST API lets you integrate ticket and client data with external tools. All API requests are scoped to a tenant and require authentication.

โš ๏ธ The API is currently in early access. Endpoints and response shapes may change.

Authentication

The API uses short-lived JWT access tokens (15-minute TTL) and long-lived refresh tokens (30-day TTL). Obtain tokens by signing in with a password or via magic link verification.

POST /api/auth/login
Content-Type: application/json

{ "email": "admin@yourdomain.com", "password": "your-password" }

Include the access token in all subsequent requests:

Authorization: Bearer <accessToken>

When the access token expires, refresh it:

POST /api/auth/refresh
{ "refreshToken": "<refreshToken>" }
โ†’ { "accessToken": "..." }

Tenant resolution

The API resolves the tenant from the request hostname. Use your tenant subdomain as the base URL:

https://your-company.serveloapp.com/api/...

Auth

MethodEndpointAuthDescription
POST/api/auth/loginNoneSign in with email and password. Returns access + refresh tokens.
POST/api/auth/magic-link/requestNoneRequest a magic link for an email address.
GET/api/auth/magic-link/verifyNoneVerify a magic link token. Returns access + refresh tokens.
POST/api/auth/refreshNoneExchange a refresh token for a new access token.
POST/api/auth/logoutNoneRevoke a refresh token.
GET/api/auth/meRequiredGet the current user's profile. Includes has_password boolean.

Users

All user endpoints require a valid access token. Role requirements are noted per route.

MethodEndpointRoleDescription
GET/api/usersAdminList all users in the org with role, status, and auth provider.
POST/api/users/inviteAdminInvite a new user. Sends a 7-day magic link invite email.
GET/api/users/techniciansAnyList active users available for ticket assignment.
GET/api/users/preferencesAnyGet the current user's preferences.
PUT/api/users/preferencesAnyMerge-update the current user's preferences.
POST/api/users/me/avatarAnyUpload a profile photo for the current user.
POST/api/users/me/set-passwordAnySet a password on the current user's account (no existing password required). Body: { password }.
POST/api/users/me/change-passwordAnyChange the current user's password. Body: { currentPassword, newPassword }.
PUT/api/users/:idAdminUpdate a user's name, role, phone, notes, or avatar URL.
POST/api/users/:id/set-passwordAdminForce-set a password for any user in the org. Body: { password }. Minimum 8 characters.
POST/api/users/:id/send-login-linkAdminSend a 24-hour magic link to a user.
PUT/api/users/:id/deactivateAdminDeactivate a user. They cannot log in until reactivated.
PUT/api/users/:id/reactivateAdminReactivate a previously deactivated user.
DELETE/api/users/:idAdminPermanently delete a user.

Tickets

MethodEndpointDescription
GET/api/ticketsList all tickets
GET/api/tickets/:idGet a single ticket
POST/api/ticketsCreate a ticket
PUT/api/tickets/:idUpdate a ticket
DELETE/api/tickets/:idMove a ticket to Trash (admin only)
GET/api/tickets/:id/commentsList comments on a ticket
POST/api/tickets/:id/commentsAdd a comment
POST/api/tickets/:id/photosUpload a photo to a ticket
DELETE/api/tickets/:id/photos/:photoIdDelete a ticket photo

Clients

MethodEndpointDescription
GET/api/customersList all clients
GET/api/customers/:idGet a single client
POST/api/customersCreate a client
PUT/api/customers/:idUpdate a client
DELETE/api/customers/:idDelete a client (admin only)

Quotes

MethodEndpointDescription
GET/api/quotesList all quotes
GET/api/quotes/:idGet a single quote
POST/api/quotesCreate a quote
PUT/api/quotes/:idUpdate a quote
POST/api/quotes/:id/sendEmail the quote to the client
DELETE/api/quotes/:idDelete a quote (admin only)

Revenue & Expenses

MethodEndpointDescription
GET/api/revenueList revenue entries
POST/api/revenueCreate a revenue entry
PUT/api/revenue/:idUpdate a revenue entry
DELETE/api/revenue/:idDelete a revenue entry (admin only)
GET/api/expensesList expense entries
POST/api/expensesCreate an expense entry
PUT/api/expenses/:idUpdate an expense entry
DELETE/api/expenses/:idDelete an expense entry (admin only)

Settings

MethodEndpointDescription
GET/api/settingsGet all settings for the org
PUT/api/settingsUpdate one or more settings (admin only)

System Admin

These endpoints require the caller to be an admin in the SYSTEM_ADMIN_ORG organization.

MethodEndpointDescription
GET/api/admin/orgsList all organizations with user counts and plan info
PUT/api/admin/orgs/:slugUpdate an org (plan, name, active status)
DELETE/api/admin/orgs/:slugPermanently delete an org and all its data
GET/api/admin/orgs/:slug/usersList all users in an org
PUT/api/admin/orgs/:slug/users/:idUpdate a user's role or active status in any org
POST/api/admin/orgs/:slug/users/:id/set-passwordForce-set a password for a user in any org. Body: { password }.
DELETE/api/admin/orgs/:slug/users/:idPermanently delete a user from any org

Error format

All error responses use the same shape:

{ "error": "Human-readable error message" }

Common status codes:

CodeMeaning
400Bad request. Missing or invalid input.
401Unauthenticated. Token missing, invalid, or expired.
403Forbidden. Authenticated but not allowed (wrong role, suspended org).
404Resource not found.
409Conflict. Typically a duplicate (e.g. email already exists).
429Rate limited. Slow down and retry.
500Server error.