Skip to main content

Directories & members

A directory is a Sally company account. These endpoints return company accounts, their memberships and users, and let admins invite and remove members.

Every endpoint below shows its parameters and response fields in the middle and a request sample with an example response on the right.

Base URL https://api.sally.ioVersion v1.0 current, not frozen yetHow versioning works

Lists the directories the authenticated user is a member of​

GET/v1.0/directories

Discovery endpoint: returns all directories of the token user (active, non-blocked memberships). The directoryId is used in the subsequent paths. Each entry carries the same fields as the single-directory endpoint.

Field overview from the specification

Response fields (per directory):

  • directoryId (string): id of the directory; use it in all /v1.0/directories/{directoryId}/... paths.
  • name (string): display name of the directory.
  • pictureFileUrl (string | null): absolute URL of the directory logo (requires the same Bearer token as the API); null if unset.
  • languageCode (string | null): default language of the directory (IETF language tag, e.g. de-DE, en); null if unset.
  • maxApiRequestsPerMinute (number): maximum number of API requests per minute allowed for this directory.
  • maxApiRequestsPerDay (number): maximum number of API requests per day allowed for this directory.

Query parameters

  • fieldsstringoptional

    Comma-separated list of the fields to return. Leave it out and you get every field — including fields added in the future, which is your call to make: name your fields if you want to be shielded from that.

    Only first-level fields can be named. A nested list such as attendees, tags or sectionItems is returned whole or not at all; attendees.name is not supported.

    On a paged response the selection applies to the entries in items; page, pageSize, total and hasMore are always returned. An unknown name is rejected with 400 rather than ignored.

    Selectable here: directoryId, languageCode, maxApiRequestsPerDay, maxApiRequestsPerMinute, name, pictureFileUrl.

    Example: directoryId,languageCode

Response

  • directoryIdstringrequired

    Unique id of the directory.

  • namestringrequired

    Display name of the directory.

  • pictureFileUrlstringrequirednullable

    Absolute URL of the directory logo, or null. Requires the same Bearer token as the API.

  • languageCodestringrequirednullable

    Default language of the directory (IETF language tag, e.g. de-DE, en-US).

  • maxApiRequestsPerMinutenumberrequired

    Maximum number of API requests per minute allowed for this directory.

  • maxApiRequestsPerDaynumberrequired

    Maximum number of API requests per day allowed for this directory.

Status codes

  • 200Success
  • 401

    Missing or invalid bearer token.

  • 429

    Rate limit exceeded (per token/IP). Transcription uploads may also return code FUP_LIMIT_EXCEEDED or TOO_MANY_CONCURRENT_TRANSCRIPTIONS.

  • 500

    Internal server error.

Returns a single directory (if the user is a member)​

GET/v1.0/directories/{directoryId}

Returns one directory by id (the caller must be a member, otherwise 404). Same shape as the discovery list.

Field overview from the specification

Response fields:

  • directoryId (string): id of the directory; use it in all /v1.0/directories/{directoryId}/... paths.
  • name (string): display name of the directory.
  • pictureFileUrl (string | null): absolute URL of the directory logo (requires the same Bearer token as the API); null if unset.
  • languageCode (string | null): default language of the directory (IETF language tag, e.g. de-DE, en); null if unset.
  • maxApiRequestsPerMinute (number): maximum number of API requests per minute allowed for this directory.
  • maxApiRequestsPerDay (number): maximum number of API requests per day allowed for this directory.

Path parameters

  • directoryIdstringrequired

    Id of the directory (the Sally company account) the resource belongs to. The directories a token can address are listed by GET /v1.0/me/directories/memberships.

Query parameters

  • fieldsstringoptional

    Comma-separated list of the fields to return. Leave it out and you get every field — including fields added in the future, which is your call to make: name your fields if you want to be shielded from that.

    Only first-level fields can be named. A nested list such as attendees, tags or sectionItems is returned whole or not at all; attendees.name is not supported.

    On a paged response the selection applies to the entries in items; page, pageSize, total and hasMore are always returned. An unknown name is rejected with 400 rather than ignored.

    Selectable here: directoryId, languageCode, maxApiRequestsPerDay, maxApiRequestsPerMinute, name, pictureFileUrl.

    Example: directoryId,languageCode

Response

  • directoryIdstringrequired

    Unique id of the directory.

  • namestringrequired

    Display name of the directory.

  • pictureFileUrlstringrequirednullable

    Absolute URL of the directory logo, or null. Requires the same Bearer token as the API.

  • languageCodestringrequirednullable

    Default language of the directory (IETF language tag, e.g. de-DE, en-US).

  • maxApiRequestsPerMinutenumberrequired

    Maximum number of API requests per minute allowed for this directory.

  • maxApiRequestsPerDaynumberrequired

    Maximum number of API requests per day allowed for this directory.

Status codes

  • 200Success
  • 400

    Invalid request (validation error).

  • 401

    Missing or invalid bearer token.

  • 404

    Resource not found or not accessible.

  • 429

    Rate limit exceeded (per token/IP). Transcription uploads may also return code FUP_LIMIT_EXCEEDED or TOO_MANY_CONCURRENT_TRANSCRIPTIONS.

  • 500

    Internal server error.

Lists the memberships of a directory (paginated, optionally filtered)​

GET/v1.0/directories/{directoryId}/memberships

Pagination via ?page + ?pageSize (max. 100). An optional ?search substring matches first/last name and email of the member (case-insensitive). Returns membership scalars only (userId, roleId, licenseId, isBlocked); fetch user details via GET .../memberships/users/{userId}. Resolve roleId/licenseId via GET /v1.0/roles / GET /v1.0/licenses.

Field overview from the specification

Response fields:

  • page / pageSize / total / hasMore: pagination envelope (current page, page size, total count, whether more pages follow).
  • items (array): the memberships on this page. Each item has:
    • directoryId (string): id of the directory this membership belongs to.
    • userId (string): id of the user this membership belongs to.
    • roleId (string): role id of the user in this directory; resolve via GET /v1.0/roles.
    • licenseId (string): license id of the user in this directory; resolve via GET /v1.0/licenses.
    • isBlocked (boolean): whether the user is blocked in this directory.

Path parameters

  • directoryIdstringrequired

    Id of the directory (the Sally company account) the resource belongs to. The directories a token can address are listed by GET /v1.0/me/directories/memberships.

Query parameters

  • pagenumberoptional

    Page number, 1-based. Defaults to 1.

  • pageSizenumberoptional

    Items per page. Defaults to 25, capped at 100.

  • searchstringoptional

    Case-insensitive substring match on first/last name and email. The term may appear at the start, middle, or end.

  • fieldsstringoptional

    Comma-separated list of the fields to return. Leave it out and you get every field — including fields added in the future, which is your call to make: name your fields if you want to be shielded from that.

    Only first-level fields can be named. A nested list such as attendees, tags or sectionItems is returned whole or not at all; attendees.name is not supported.

    On a paged response the selection applies to the entries in items; page, pageSize, total and hasMore are always returned. An unknown name is rejected with 400 rather than ignored.

    Selectable here: directoryId, isBlocked, licenseId, roleId, userId.

    Example: directoryId,isBlocked

Response: each entry in items

  • directoryIdstringrequired

    Id of the directory this membership belongs to.

  • userIdstringrequired

    Id of the user this membership belongs to.

  • roleIdstringrequired

    Role id of the user in this directory. Resolve via GET /v1.0/roles.

  • licenseIdstringrequired

    License id of the user in this directory. Resolve via GET /v1.0/licenses.

  • isBlockedbooleanrequired

    Whether the user is blocked in this directory.

Every page also carries page, pageSize, total, hasMore.

Status codes

  • 200Success
  • 400

    Invalid request (validation error).

  • 401

    Missing or invalid bearer token.

  • 404

    Resource not found or not accessible.

  • 429

    Rate limit exceeded (per token/IP). Transcription uploads may also return code FUP_LIMIT_EXCEEDED or TOO_MANY_CONCURRENT_TRANSCRIPTIONS.

  • 500

    Internal server error.

Invites/creates a user in the directory​

POST/v1.0/directories/{directoryId}/memberships

Creates a membership by inviting a user (by email) with a role + license. Only admins/owners may invite; only an owner may invite another owner. Fails with 400 if no free license seat is available.

Field overview from the specification

Body fields:

  • email (string, required): email address to invite.
  • roleId (string, required): role id to assign; resolve valid ids via GET /v1.0/roles.
  • licenseId (string, required): license id to assign; resolve valid ids via GET /v1.0/licenses.
  • description (string, optional): free-text note.
  • languageCode (string, optional): invitation language (IETF language tag, e.g. de-DE).

Path parameters

  • directoryIdstringrequired

    Id of the directory (the Sally company account) the resource belongs to. The directories a token can address are listed by GET /v1.0/me/directories/memberships.

Query parameters

  • fieldsstringoptional

    Comma-separated list of the fields to return. Leave it out and you get every field — including fields added in the future, which is your call to make: name your fields if you want to be shielded from that.

    Only first-level fields can be named. A nested list such as attendees, tags or sectionItems is returned whole or not at all; attendees.name is not supported.

    On a paged response the selection applies to the entries in items; page, pageSize, total and hasMore are always returned. An unknown name is rejected with 400 rather than ignored.

    Selectable here: createdOn, inviteeEmail, licenseId, roleId, userId.

    Example: createdOn,inviteeEmail

Request body application/json

  • emailstringrequired

    Email address to invite.

  • roleIdstringrequired

    Role id to assign. Resolve valid ids via GET /v1.0/roles.

  • licenseIdstringrequired

    License id to assign. Resolve valid ids via GET /v1.0/licenses.

  • descriptionstringoptionalnullable

    Optional note.

  • languageCodestringoptionalnullable

    Optional invitation language as an IETF language tag (e.g. de-DE).

Response

  • userIdstringrequired

    Id of the invited user.

  • inviteeEmailstringrequirednullable

    Invited email address.

  • roleIdstringrequired

    Assigned role id.

  • licenseIdstringrequired

    Assigned license id.

  • createdOnstringrequired

    Creation timestamp (ISO-8601).

Status codes

  • 200Success
  • 400

    Invalid request (validation error).

  • 401

    Missing or invalid bearer token.

  • 403

    Forbidden (insufficient permissions).

  • 404

    Resource not found or not accessible.

  • 429

    Rate limit exceeded (per token/IP). Transcription uploads may also return code FUP_LIMIT_EXCEEDED or TOO_MANY_CONCURRENT_TRANSCRIPTIONS.

  • 500

    Internal server error.

Lists the users of a directory (paginated, optionally filtered)​

GET/v1.0/directories/{directoryId}/memberships/users

Basic user info of all members of the directory. Pagination via ?page + ?pageSize (max. 100). An optional ?search substring matches first/last name and email (case-insensitive). The caller must be a member of the directory.

Field overview from the specification

Response fields:

  • page / pageSize / total / hasMore: pagination envelope (current page, page size, total count, whether more pages follow).
  • items (array): the users on this page. Each item has:
    • userId (string): id of the user.
    • email (string): email address of the user.
    • firstName (string): first name.
    • lastName (string): last name.
    • pictureFileUrl (string | null): absolute URL of the profile picture, or null. Requires the same Bearer token as the API.

Path parameters

  • directoryIdstringrequired

    Id of the directory (the Sally company account) the resource belongs to. The directories a token can address are listed by GET /v1.0/me/directories/memberships.

Query parameters

  • pagenumberoptional

    Page number, 1-based. Defaults to 1.

  • pageSizenumberoptional

    Items per page. Defaults to 25, capped at 100.

  • searchstringoptional

    Case-insensitive substring match on first/last name and email. The term may appear at the start, middle, or end.

  • fieldsstringoptional

    Comma-separated list of the fields to return. Leave it out and you get every field — including fields added in the future, which is your call to make: name your fields if you want to be shielded from that.

    Only first-level fields can be named. A nested list such as attendees, tags or sectionItems is returned whole or not at all; attendees.name is not supported.

    On a paged response the selection applies to the entries in items; page, pageSize, total and hasMore are always returned. An unknown name is rejected with 400 rather than ignored.

    Selectable here: email, firstName, lastName, pictureFileUrl, userId.

    Example: email,firstName

Response: each entry in items

  • userIdstringrequired

    Id of the user.

  • emailstringrequired

    Email address of the user.

  • firstNamestringrequired

    First name.

  • lastNamestringrequired

    Last name.

  • pictureFileUrlstringrequirednullable

    Absolute URL of the profile picture, or null. Requires the same Bearer token as the API.

Every page also carries page, pageSize, total, hasMore.

Status codes

  • 200Success
  • 400

    Invalid request (validation error).

  • 401

    Missing or invalid bearer token.

  • 404

    Resource not found or not accessible.

  • 429

    Rate limit exceeded (per token/IP). Transcription uploads may also return code FUP_LIMIT_EXCEEDED or TOO_MANY_CONCURRENT_TRANSCRIPTIONS.

  • 500

    Internal server error.

Searches the users of a directory (parameters in the body)​

POST/v1.0/directories/{directoryId}/memberships/users/search

The caller must be a member of the directory.

Field overview from the specification

Body fields:

  • search (string, optional): case-insensitive substring on first/last name and email; the term may appear at the start, middle, or end.
  • page (number, optional, default 1): 1-based page number.
  • pageSize (number, optional, default 25): page size (max. 100).

Path parameters

  • directoryIdstringrequired

    Id of the directory (the Sally company account) the resource belongs to. The directories a token can address are listed by GET /v1.0/me/directories/memberships.

Query parameters

  • fieldsstringoptional

    Comma-separated list of the fields to return. Leave it out and you get every field — including fields added in the future, which is your call to make: name your fields if you want to be shielded from that.

    Only first-level fields can be named. A nested list such as attendees, tags or sectionItems is returned whole or not at all; attendees.name is not supported.

    On a paged response the selection applies to the entries in items; page, pageSize, total and hasMore are always returned. An unknown name is rejected with 400 rather than ignored.

    Selectable here: email, firstName, lastName, pictureFileUrl, userId.

    Example: email,firstName

Request body application/json

  • searchstringoptionalnullable

    Case-insensitive substring match on first/last name and email. The term may appear at the start, middle, or end.

  • pagenumberoptional

    Page (1-based, default 1).

  • pageSizenumberoptional

    Page size (default 25, max 100).

Response: each entry in items

  • userIdstringrequired

    Id of the user.

  • emailstringrequired

    Email address of the user.

  • firstNamestringrequired

    First name.

  • lastNamestringrequired

    Last name.

  • pictureFileUrlstringrequirednullable

    Absolute URL of the profile picture, or null. Requires the same Bearer token as the API.

Every page also carries page, pageSize, total, hasMore.

Status codes

  • 200Success
  • 400

    Invalid request (validation error).

  • 401

    Missing or invalid bearer token.

  • 403

    Forbidden (insufficient permissions).

  • 404

    Resource not found or not accessible.

  • 429

    Rate limit exceeded (per token/IP). Transcription uploads may also return code FUP_LIMIT_EXCEEDED or TOO_MANY_CONCURRENT_TRANSCRIPTIONS.

  • 500

    Internal server error.

Returns a single user of a directory​

GET/v1.0/directories/{directoryId}/memberships/users/{userId}

Basic user info by id. The caller must be a member of the directory, and the requested user must be a member of the same directory — otherwise 404 (no existence leak).

Field overview from the specification

Response fields:

  • userId (string): id of the user.
  • email (string): email address of the user.
  • firstName (string): first name.
  • lastName (string): last name.
  • pictureFileUrl (string | null): absolute URL of the profile picture, or null. Requires the same Bearer token as the API.

Path parameters

  • directoryIdstringrequired

    Id of the directory (the Sally company account) the resource belongs to. The directories a token can address are listed by GET /v1.0/me/directories/memberships.

  • userIdstringrequired

    Id of the user.

Query parameters

  • fieldsstringoptional

    Comma-separated list of the fields to return. Leave it out and you get every field — including fields added in the future, which is your call to make: name your fields if you want to be shielded from that.

    Only first-level fields can be named. A nested list such as attendees, tags or sectionItems is returned whole or not at all; attendees.name is not supported.

    On a paged response the selection applies to the entries in items; page, pageSize, total and hasMore are always returned. An unknown name is rejected with 400 rather than ignored.

    Selectable here: email, firstName, lastName, pictureFileUrl, userId.

    Example: email,firstName

Response

  • userIdstringrequired

    Id of the user.

  • emailstringrequired

    Email address of the user.

  • firstNamestringrequired

    First name.

  • lastNamestringrequired

    Last name.

  • pictureFileUrlstringrequirednullable

    Absolute URL of the profile picture, or null. Requires the same Bearer token as the API.

Status codes

  • 200Success
  • 400

    Invalid request (validation error).

  • 401

    Missing or invalid bearer token.

  • 404

    Resource not found or not accessible.

  • 429

    Rate limit exceeded (per token/IP). Transcription uploads may also return code FUP_LIMIT_EXCEEDED or TOO_MANY_CONCURRENT_TRANSCRIPTIONS.

  • 500

    Internal server error.

Removes a user from the directory​

DELETE/v1.0/directories/{directoryId}/memberships/{userId}

Revokes the membership of the user. Only admins/owners may remove members; the last owner cannot be removed. If it was the user’s last directory, the user is deleted entirely (GDPR).

Path parameters

  • directoryIdstringrequired

    Id of the directory (the Sally company account) the resource belongs to. The directories a token can address are listed by GET /v1.0/me/directories/memberships.

  • userIdstringrequired

    Id of the user.

Query parameters

  • fieldsstringoptional

    Comma-separated list of the fields to return. Leave it out and you get every field — including fields added in the future, which is your call to make: name your fields if you want to be shielded from that.

    Only first-level fields can be named. A nested list such as attendees, tags or sectionItems is returned whole or not at all; attendees.name is not supported.

    On a paged response the selection applies to the entries in items; page, pageSize, total and hasMore are always returned. An unknown name is rejected with 400 rather than ignored.

    Selectable here: userHardDeleted.

    Example: userHardDeleted

Response

  • userHardDeletedbooleanrequired

    True if the user had no other directories and was therefore deleted entirely (GDPR).

Status codes

  • 200Success
  • 400

    Invalid request (validation error).

  • 401

    Missing or invalid bearer token.

  • 403

    Forbidden (insufficient permissions).

  • 404

    Resource not found or not accessible.

  • 429

    Rate limit exceeded (per token/IP). Transcription uploads may also return code FUP_LIMIT_EXCEEDED or TOO_MANY_CONCURRENT_TRANSCRIPTIONS.

  • 500

    Internal server error.