Skip to content
API pagesUsers

API documentation

Users

The signed-in person, as distinct from the organization they act in. These routes are about one human account: their name, their email, their language, and their picture.

All four routes here are not organization-scoped. They answer without X-Organization-Id, because they are the routes a client calls before it knows which organization to ask about.

If you are writing a server integration with an API key, you will rarely need this page. A key is not a person. GET /v1/users/me answers with the person who created the key.

Routes

Method Path Needs
GET /v1/users/me Any credential
POST /v1/users/me/avatar Any credential. Acts on the caller only
DELETE /v1/users/me/avatar Any credential. Acts on the caller only
POST /v1/onboarding/session A session token, right after signing in

GET /v1/users/me

The current person.

Field Type Means
id uuid The Syllevo user id
email string Their address
firstName string or null Null until they fill it in
lastName string or null Null until they fill it in
locale string en or ro
avatarUrl string or null Picture, 256 px. A short-lived link
avatarThumbnailUrl string or null Picture, 64 px. A short-lived link
GET /v1/users/me HTTP/1.1
Host: api.syllevo.com
X-Api-Key: syl_live_examplekeynotreal000000000000
{
  "id": "66666666-6666-4666-8666-666666666666",
  "email": "maria@example.com",
  "firstName": "Maria",
  "lastName": "Popescu",
  "locale": "ro",
  "avatarUrl": null,
  "avatarThumbnailUrl": null
}

This person's locale decides the language of the interface and of anything Syllevo sends to them directly. It is separate from the organization's locale, which decides the language of what clients receive. See Organizations.

POST and DELETE /v1/users/me/avatar

Sets or removes the caller's own picture.

The upload is multipart/form-data with one part named file, at most 5 MB, stored as WebP at 256 px with a 64 px thumbnail. The same rules as the organization logo. See Organizations.

There is no route for setting somebody else's picture, and that is deliberate. The row the picture lands on is decided by the route and by the credential, never by a field in the form, so /v1/users/me/avatar has no way to name a colleague.

Both answer 200 with the person. The delete is idempotent: removing a picture that is already gone answers 200, not 404.

POST /v1/onboarding/session

The first call a web client makes after sign-in. It creates the person's row if this is their first visit, then answers with everything a client needs to decide what to show next.

Send no body. On production hosts a body is ignored entirely, and an empty POST is accepted rather than refused.

Field Type Means
user object The same shape as GET /v1/users/me
organizations array The same shape as GET /v1/organizations
pendingInvitations array Invitations waiting for this person. See below

Each pending invitation:

Field Type Means
id uuid Accept or decline it with this
organizationId uuid The firm inviting them
organizationName string Its name
organizationKind OrganizationKind 0 firm, 1 business
role OrganizationRole The role they would get
invitedByName string or null Who sent it, when that is known
expiresAt date-time After this the invitation is dead
hasOrganizationWideAccess boolean Whether the invitation grants every client
grantedProfileCount integer How many clients it grants, when it is not org-wide
POST /v1/onboarding/session HTTP/1.1
Host: api.syllevo.com
Authorization: Bearer <session token>
Content-Length: 0
{
  "user": {
    "id": "66666666-6666-4666-8666-666666666666",
    "email": "maria@example.com",
    "firstName": "Maria",
    "lastName": "Popescu",
    "locale": "ro",
    "avatarUrl": null,
    "avatarThumbnailUrl": null
  },
  "organizations": [],
  "pendingInvitations": [
    {
      "id": "77777777-7777-4777-8777-777777777777",
      "organizationId": "11111111-1111-4111-8111-111111111111",
      "organizationName": "Example Contabil SRL",
      "organizationKind": 0,
      "role": 0,
      "invitedByName": "Andrei Ionescu",
      "expiresAt": "2026-09-25T09:00:00Z",
      "hasOrganizationWideAccess": false,
      "grantedProfileCount": 3
    }
  ]
}

Three outcomes are worth branching on:

  • organizations is empty and pendingInvitations is empty. Send them to create an organization.
  • organizations is empty and there is an invitation. Send them to accept it. See Team, roles, and invitations.
  • organizations has entries. Pick one and start sending X-Organization-Id.