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

Claude connector (MCP)

Servelo exposes a remote MCP server so it can be added as a custom connector in Claude, letting you ask Claude to read and act on your live Servelo data directly from chat.

  1. In claude.ai, go to Settings > Connectors > Add custom connector
  2. Enter https://serveloapp.com/mcp as the connector URL
  3. Claude redirects you to Servelo's login (or your existing session) to authorize access, using the same OAuth-style consent screen any third-party app would show
  4. Approve the connection. Claude can now call the tools listed below on your behalf

Every tool call is authenticated as you and enforces the same roles and validation as the equivalent page in the app; nothing is reimplemented or given broader access. Excluded from the tool surface entirely: org/user/billing/plan management, SSO/MFA settings, deletion, and password changes.

AreaTools
Ticketslist, get, create, update, add comment
Customerslist, get, create, update
Quoteslist, get, create
Invoiceslist, get, create
Technicianslist
Assetslist, get
Revenue & Expenseslist
Othersearch, dashboard summary

Manage or revoke access any time from My Account > Connected Apps. Revoking immediately invalidates that connection's access.

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.