Accounts API

The Accounts API is how you manage the people in your Droplet organization. Use it to look up who exists, pull full account records, create new accounts, keep profiles and custom attributes up to date, assign roles, organize accounts with managed tags, archive and restore accounts, and help people reset their passwords. Everything an admin can do to a person in the Droplet UI has a matching endpoint here.

Accounts API

The basics

All endpoints live under the base URL https://api.droplet.io and the slice paths below append to it. For example, listing account IDs is a request to GET https://api.droplet.io/v1/accounts/ids.

Every request must include a bearer token in the Authorization header:

Authorization: Bearer <token>

The token is a JWT issued for your organization. Requests without a valid token are rejected.

Successful responses share a common envelope:

{
  "requestId": "req_8f2c...",
  "success": true,
  "data": { /* ... */ }
}

When something goes wrong, success is false and an error object replaces data:

{
  "requestId": "req_8f2c...",
  "success": false,
  "error": {
    "code": "not_found",
    "message": "Account does not exist."
  }
}

The requestId is included on every response, success or failure. Keep it handy when contacting support so we can trace exactly what happened.

Path parameters are written with a leading colon, such as :key or :id. These are placeholders. Replace the whole token, including the colon, with a real value when you build the URL.

The account object

Several endpoints return a full account record. Here is the shape you can expect, so we do not repeat it in full for every endpoint:

{
  "id": "acc_4Kq9...",
  "created": "2026-01-12T09:30:00Z",
  "modified": "2026-06-18T14:02:11Z",
  "archived": false,
  "email": "jordan@acme.com",
  "avatar": "https://cdn.droplet.io/avatars/acc_4Kq9.png",
  "firstName": "Jordan",
  "lastName": "Rivera",
  "fullName": "Jordan Rivera",
  "phone": "+1 555 010 2244",
  "title": "Operations Lead",
  "department": "Operations",
  "notifications": { "email": true, "app": true },
  "ssoEnabled": true,
  "sudo": false,
  "metadata": { /* ... */ },
  "tags": { "region": "emea" },
  "tagsModified": "2026-05-02T11:20:00Z",
  "roleIds": ["role_admin", "role_reviewer"],
  "lastLogin": "2026-06-19T08:15:42Z",
  "termsOfServiceAccepted": "2026-01-12T09:31:00Z",
  "permissions": { "forms.create": true, "accounts.manage": false },
  "attributes": { /* ... */ }
}

Only id is guaranteed on every record. Timestamps are ISO 8601 and may be null when an event has not occurred yet (for example, lastLogin on an account that has never signed in). A record may include additional fields over time, so ignore any you do not recognize.

The include query parameter, supported on the create, update, and entities endpoints, accepts a comma-separated list of fields such as fullName,email. Use it to trim the returned record down to just the fields you care about.

Listing and lookup

List matching account IDs

GET /v1/accounts/ids

Returns the account IDs that match your filter criteria, along with a total count. This is the workhorse for pagination, search, and filtering. The typical flow is to call this endpoint to get a page of IDs, then pass those IDs to the entities endpoint to fetch the full records.

ParameterInTypeDescription
pagequeryintegerZero-based page index. Defaults to the first page.
roleIdquerystringOnly return accounts that hold this role.
searchquerystringFree-text search across name and email.
tagKeyquerystringFilter by a managed tag key. Pair with tagValue.
tagValuequerystringThe value the tagKey must match.
showquerystringWhich accounts to include: all, active, archived, or voided.
curl "https://api.droplet.io/v1/accounts/ids?show=active&search=jordan&page=0" \
  -H "Authorization: Bearer <token>"
{
  "requestId": "req_8f2c...",
  "success": true,
  "data": {
    "count": 3,
    "ids": ["id1", "id2", "id3"]
  }
}

Fetch account records by ID

POST /v1/accounts/entities

Returns full account records for a list of IDs. Pair this with the IDs endpoint to hydrate a page of results into complete account objects.

FieldInTypeRequiredDescription
idsbodyarrayYesThe account IDs to fetch.
includequerystringNoComma-separated fields to return, for example fullName,email.
curl -X POST "https://api.droplet.io/v1/accounts/entities?include=fullName,email" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{ "ids": ["id1", "id2", "id3"] }'
{
  "requestId": "req_8f2c...",
  "success": true,
  "data": [
    { "id": "id1", "fullName": "Jordan Rivera", "email": "jordan@acme.com" },
    { "id": "id2", "fullName": "Sam Okoro", "email": "sam@acme.com" }
    // ...
  ]
}

Creating and updating

Create an account

POST /v1/accounts

Creates a new account in your organization. Only an email and a full name are required to get started. The new person can fill in the rest of their profile later, or you can set it via the update endpoints.

FieldInTypeRequiredDescription
emailbodystringYesThe account's email address. Used for sign-in.
fullNamebodystringYesThe person's display name.
includequerystringNoComma-separated fields to return on the created record.
curl -X POST "https://api.droplet.io/v1/accounts" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{ "email": "newhire@acme.com", "fullName": "Casey Lin" }'
{
  "requestId": "req_8f2c...",
  "success": true,
  "data": {
    "id": "acc_9Tz2...",
    "email": "newhire@acme.com",
    "fullName": "Casey Lin",
    "archived": false,
    "roleIds": []
    // ... full account object
  }
}

Update the current account

PUT /v1/accounts/current

Updates the profile of the account that owns the bearer token. This is the endpoint a user calls to edit their own details. All fields are optional, so send only what is changing.

FieldTypeDescription
firstNamestringGiven name.
lastNamestringFamily name.
phonestringContact phone number.
titlestringJob title.
departmentstringDepartment name.
notificationsobjectNotification preferences: { "email": bool, "app": bool }.

The include query parameter is also supported to shape the returned record.

curl -X PUT "https://api.droplet.io/v1/accounts/current" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Senior Operations Lead",
    "notifications": { "email": true, "app": false }
  }'
{
  "requestId": "req_8f2c...",
  "success": true,
  "data": {
    "id": "acc_4Kq9...",
    "title": "Senior Operations Lead",
    "notifications": { "email": true, "app": false }
    // ... full account object
  }
}

Update custom attributes

PUT /v1/accounts/attributes

Replaces the custom attributes for a given account. Attributes are a structured set of directory-style fields (identity, address, employment, and nine free-form custom slots) that you can sync from an external system of record such as an HRIS or identity provider.

When you send the attributes object, the full set of attribute fields is expected, and unknown fields are rejected. Treat this as a full replacement of the attribute block rather than a partial patch. To clear a value, send it as an empty string.

FieldTypeRequiredDescription
accountIdstringYesThe account whose attributes you are setting.
attributesobjectNoThe attribute block. See the fields below.

The attributes object accepts these fields: externalId, firstName, lastName, fullName, primaryEmail, secondaryEmail, username, jobTitle, state (one of active or inactive), createdAt, updatedAt, streetAddress, locality, region, postalCode, country, rawAddress, costCenterName, departmentName, divisionName, employeeType, employmentStartDate, managerEmail, and customAttribute1 through customAttribute9.

curl -X PUT "https://api.droplet.io/v1/accounts/attributes" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "accountId": "acc_4Kq9...",
    "attributes": {
      "externalId": "EMP-10482",
      "firstName": "Jordan",
      "lastName": "Rivera",
      "fullName": "Jordan Rivera",
      "primaryEmail": "jordan@acme.com",
      "secondaryEmail": "",
      "username": "jrivera",
      "jobTitle": "Operations Lead",
      "state": "active",
      "createdAt": "2026-01-12",
      "updatedAt": "2026-06-18",
      "streetAddress": "12 Market St",
      "locality": "Dublin",
      "region": "Leinster",
      "postalCode": "D02",
      "country": "IE",
      "rawAddress": "12 Market St, Dublin, D02, IE",
      "costCenterName": "OPS-EU",
      "departmentName": "Operations",
      "divisionName": "EMEA",
      "employeeType": "full_time",
      "employmentStartDate": "2024-03-01",
      "managerEmail": "lead@acme.com",
      "customAttribute1": "",
      "customAttribute2": "",
      "customAttribute3": "",
      "customAttribute4": "",
      "customAttribute5": "",
      "customAttribute6": "",
      "customAttribute7": "",
      "customAttribute8": "",
      "customAttribute9": ""
    }
  }'

This endpoint returns the bare success envelope, with no data payload:

{
  "requestId": "req_8f2c...",
  "success": true
}

Roles

Add roles to accounts

POST /v1/accounts/add-roles

Grants one or more roles to one or more accounts in a single call. Roles drive what each person can see and do, so this is how you bulk-promote a set of people.

FieldTypeRequiredDescription
idsarrayYesThe accounts to update.
roleIdsarrayYesThe roles to add to each account.
curl -X POST "https://api.droplet.io/v1/accounts/add-roles" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{ "ids": ["id1", "id2"], "roleIds": ["role_reviewer"] }'
{
  "requestId": "req_8f2c...",
  "success": true,
  "data": { "count": 2 }
}

Remove roles from accounts

POST /v1/accounts/remove-roles

The mirror of adding roles. Revokes the listed roles from each of the listed accounts.

FieldTypeRequiredDescription
idsarrayYesThe accounts to update.
roleIdsarrayYesThe roles to remove from each account.
curl -X POST "https://api.droplet.io/v1/accounts/remove-roles" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{ "ids": ["id1", "id2"], "roleIds": ["role_reviewer"] }'
{
  "requestId": "req_8f2c...",
  "success": true,
  "data": { "count": 2 }
}

Managed tags

Managed tags are key and value pairs you can attach to accounts to group and filter them. Each tag operation targets a single tag key, supplied in the path, and applies to a batch of accounts.

Add a tag value

PUT /v1/accounts/tags/:key/add

Sets the value of the managed tag :key on each of the specified accounts.

FieldInTypeRequiredDescription
:keypathstringYesThe managed tag key to set.
idsbodyarrayYesThe accounts to tag.
valuebodyanyYesThe value to store for this tag key.
curl -X PUT "https://api.droplet.io/v1/accounts/tags/region/add" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{ "ids": ["id1", "id2"], "value": "emea" }'
{
  "requestId": "req_8f2c...",
  "success": true
}

Remove a tag

PUT /v1/accounts/tags/:key/remove

Removes the managed tag :key from each of the specified accounts.

FieldInTypeRequiredDescription
:keypathstringYesThe managed tag key to remove.
idsbodyarrayYesThe accounts to untag.
curl -X PUT "https://api.droplet.io/v1/accounts/tags/region/remove" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{ "ids": ["id1", "id2"] }'
{
  "requestId": "req_8f2c...",
  "success": true
}

Archive and restore

Archive accounts

POST /v1/accounts/archive

Archives the specified accounts. Archived accounts can no longer sign in but are kept on record, so this is the safe way to deactivate someone without losing their history. Restore them later if needed.

FieldTypeRequiredDescription
idsarrayYesThe accounts to archive.
curl -X POST "https://api.droplet.io/v1/accounts/archive" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{ "ids": ["id1", "id2", "id3"] }'
{
  "requestId": "req_8f2c...",
  "success": true,
  "data": { "count": 3 }
}

Before archiving, consider calling scan references (below) to see whether the account is still wired into any forms or datasets.

Restore accounts

POST /v1/accounts/restore

Reactivates accounts that were previously archived, returning them to active status.

FieldTypeRequiredDescription
idsarrayYesThe archived accounts to restore.
curl -X POST "https://api.droplet.io/v1/accounts/restore" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{ "ids": ["id1", "id2", "id3"] }'
{
  "requestId": "req_8f2c...",
  "success": true,
  "data": { "count": 3 }
}

References and password resets

Scan for references to an account

POST /v1/accounts/scan-references

Scans your forms and datasets for places that reference a given account, such as assignment steps, notifications, and dataset columns. Run this before archiving or removing someone so you know exactly where they are wired in and nothing breaks downstream.

FieldTypeRequiredDescription
accountIdstringYesThe account to scan for.
curl -X POST "https://api.droplet.io/v1/accounts/scan-references" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{ "accountId": "acc_4Kq9..." }'
{
  "requestId": "req_8f2c...",
  "success": true,
  "data": {
    "forms": [
      {
        "formId": "frm_2a...",
        "formName": "Expense Approval",
        "formType": "workflow",
        "references": [
          {
            "location": "step",
            "stepId": "step_3",
            "stepLabel": "Manager Review",
            "elementType": "assignee",
            "field": "assignedTo",
            "context": "Assigned reviewer"
          }
          // ...
        ]
      }
    ],
    "datasets": [
      {
        "datasetId": "ds_9f...",
        "datasetName": "Employee Directory",
        "matchCount": 2,
        "columns": ["owner", "manager"]
      }
    ]
  }
}

Within each form reference, location, field, and context are always present, while stepId, stepLabel, notificationId, elementId, and elementType appear depending on where the reference was found.

Request a password reset by ID

POST /v1/accounts/:id/request-password-reset

Triggers a password reset email for a specific account, identified by its ID. Use this when you already know the account ID, for example from a lookup.

FieldInTypeRequiredDescription
:idpathstringYesThe account to send a reset to.
curl -X POST "https://api.droplet.io/v1/accounts/acc_4Kq9.../request-password-reset" \
  -H "Authorization: Bearer <token>"
{
  "requestId": "req_8f2c...",
  "success": true
}

Request a password reset by email

POST /v1/accounts/:organizationId/request-password-reset-by-email/:email

Triggers a password reset for an account identified by its email within a specific organization. This is handy when you have the person's email but not their account ID.

FieldInTypeRequiredDescription
:organizationIdpathstringYesThe organization the account belongs to.
:emailpathstringYesThe account's email address. URL-encode it.
curl -X POST "https://api.droplet.io/v1/accounts/org_77z.../request-password-reset-by-email/jordan%40acme.com" \
  -H "Authorization: Bearer <token>"
{
  "requestId": "req_8f2c...",
  "success": true
}

Because the email is part of the URL path, remember to URL-encode it. The @ symbol becomes %40.

Last reviewed by Nick Duell and published on June 22, 2026 3PM ET