Crew has a small read-only API for connecting your own tools: a staff page, a spreadsheet, a bot. It never changes anything, and it never returns contact details, notes, disciplinary records or leave reasons.

Warning: The API sends your organization's data to systems you control. Your organization is responsible for keeping keys safe and for what those systems do with the data.

Creating an API key

Super Users open Settings → Integrations → API keys and create a key with:

  • a name, so you know what it's for (for example Website staff page);
  • one or more scopes: what the key may read.
Scope Gives access to
employees:read /v1/employees (members, no contact details)
departments:read /v1/departments
requests:read /v1/requests
leave:read /v1/leave (who is away, no reasons)

/v1/organization works with any key.

The key looks like crew_<server ID>_<secret> and is shown once. Store it somewhere safe, such as your server's environment variables, never in a website's public code. The list shows each key's last four characters and when it was last used. Revoke a key at any time; it stops working immediately. An organization can have up to 10 active keys.

Making requests

Send the key as a bearer token:

curl https://crew.noyralabs.com/v1/employees \
  -H "Authorization: Bearer crew_123456789012345678_yourSecretHere"
  • All endpoints are GET and return JSON.
  • The API is for servers, not browsers: there's no CORS, so a web page can't call it directly. Call it from your backend and pass on what you need.
  • Each key can make 240 requests a minute. Above that you get 429 with Retry-After: 60.
  • Responses aren't cached (Cache-Control: no-store). Cache on your side if you call often.

Endpoints

GET /v1/organization

{ "guildId": "123456789012345678", "name": "Lumen Collective", "memberCount": 48 }

memberCount counts everyone who isn't terminated.

GET /v1/employees

Scope employees:read. Every member, as { "data": [ … ] }:

{
  "data": [
    {
      "id": "1001",
      "name": "Maya Chen",
      "title": "Team Lead",
      "departmentId": "3f6b2c1e-8a4d-4c2e-9b1f-2d7e5a9c0b41",
      "unitId": null,
      "managerId": "1000",
      "employmentStatus": "active",
      "workerType": "internal",
      "hireDate": "2026-01-15",
      "discordId": "234567890123456789"
    }
  ]
}

employmentStatus is active, on_leave or terminated; workerType is internal, external or contractor. Terminated members are included, so filter them out if you only want current staff.

GET /v1/employees/{id}

Scope employees:read. One member, same fields, or 404.

GET /v1/departments

Scope departments:read. Departments with their units, sorted by name:

{
  "data": [
    {
      "id": "3f6b2c1e-8a4d-4c2e-9b1f-2d7e5a9c0b41",
      "name": "Support",
      "units": [{ "id": "9c1d7e2a-5b3f-4e8a-a6c2-7f0e1d4b8a53", "name": "Weekend team" }]
    }
  ]
}

GET /v1/requests

Scope requests:read. The 500 most recent requests, newest first:

{
  "data": [
    {
      "id": "b2e4f6a8-1c3d-4e5f-8a9b-0c1d2e3f4a5b",
      "number": "REQCREW000042",
      "type": "leave",
      "status": "approved",
      "employeeId": "1001",
      "submittedAt": "2026-10-20T09:12:00.000Z",
      "decidedAt": "2026-10-20T15:40:00.000Z"
    }
  ]
}

No request details or reasons are included. Decided requests disappear after 7 days, like in the app.

GET /v1/leave

Scope leave:read. Approved leave that ended in the last 30 days, is happening now or is coming up:

{
  "data": [
    {
      "id": "e7d9c1b3-2a4f-4b6d-9e8c-1f3a5b7d9c2e",
      "employeeId": "1001",
      "startDate": "2026-11-02",
      "endDate": "2026-11-06"
    }
  ]
}

Errors

Errors are JSON with an error message:

Status Meaning
401 The key is missing, malformed or revoked.
403 The key lacks the scope for this endpoint, or the organization is archived.
404 No such endpoint or record.
429 Too many requests. Wait a minute.
500 Something went wrong on Crew's side. Try again later.

Prefer pushing over polling? See Webhooks.

Still need a hand?

Open a ticket in our Discord, and our team will help you out.

Open a ticket