API reference
Password sets
Make password sets, save the passwords a task signs in with, and archive or delete them.
A password set is a group of passwords a task can sign in with. A password is a secret a worker uses on a website or in an app that you allow: an API key, or an app's sign-in. You put a value in and a task uses it, and no route ever answers the value back. Password sets explains why, and who answers a first use.
Every worker has a set of its own, which holds the passwords saved on that worker, and the workspace has one shared set. You can make more. A task signs in with the sets named in its password_set_ids. Unless it names others, that is the worker's own set, then the shared set, and the first set that has a sign-in for an app is the one used. A set holds up to 256 passwords.
A password is one of three kinds, by its auth.type:
auth.type |
What it is | Where a task uses it |
|---|---|---|
environment_variable |
A value a command uses under a name. The command sees a stand-in, and Little Worker puts the real value in each request to one of the password's websites. | In a request to one of its allowed_hosts, in the places injection_location allows. |
mcp_oauth |
An app's sign-in: an access token and, if you give it, the settings to refresh it. | In calls to the app at its app_url. |
static_bearer |
A fixed token for an app, such as an API key. | In calls to the app at its app_url, as Authorization: Bearer. |
An app sign-in goes in the shared set or a set you made, never in a worker's own set. A set holds one sign-in for each app.
A set can be personal. Make it with owner set to me, and it belongs to you: you and the workspace's owners see it, and only the tasks you start may name it. A routine cannot name it.
The password set object
The routes for sets answer a set, or a list of them. The routes for passwords answer a password, which has its own fields under Save a password. Times are RFC 3339 in UTC, to the millisecond.
Fields
typestringAlwayspassword_set.idpassword set idThe set's id:password_set_and 32 hex digits.display_namestringThe set's name, 1 to 255 characters. Until someone renames it, a worker's own set has the worker's name, and the shared set isShared passwords.metadataobjectYour own labels for the set: up to 16 keys of 1 to 64 characters, each with a string value of up to 512.created_attimeWhen the set was made.updated_attimeWhen the set last changed.archived_attime or nullWhen the set was archived.nullwhile it is not.owneruser id or nullThe member a personal set belongs to, as theiruser_id.nullfor a set every member of the workspace shares. Only the owner and a workspace owner see a personal set.
{
"type": "password_set",
"id": "password_set_597a64d52e7f4e84ac5d95929bf4cbae",
"display_name": "Billing",
"metadata": {
"team": "ops"
},
"created_at": "2026-10-20T09:14:02.331Z",
"updated_at": "2026-10-20T09:14:02.331Z",
"archived_at": null,
"owner": null
}Make a password set
POST/password_sets
Make an empty set. It is shared by the workspace unless you make it personal with owner.
Body
display_namestringRequiredThe set's name, 1 to 255 characters.metadataobjectYour own labels for the set: up to 16 keys of 1 to 64 characters, each with a string value of up to 512.ownerstringme, or your ownuser_id, makes a personal set that belongs to you. Left out ornull, the set is shared. A set cannot be made for another member, and its owner never changes.
Returns
200 and the set.
Errors
| Status | Type | When |
|---|---|---|
| 400 | invalid_request_error | A field is not valid (error_code validation_error): display_name is empty or over 255 characters, metadata breaks its limits, or owner is another member's id. A personal set belongs to the member who makes it. |
| 401 | authentication_error | The key is missing, removed, or not a key. Send it in x-api-key. |
| 429 | rate_limit_error | The workspace made too many requests this minute. Wait the seconds in Retry-After, then try again. |
curl "https://core.thelittleworker.com/api/v1/password_sets" \
-H "x-api-key: $LITTLE_WORKER_API_KEY" \
-H "Little-Worker-Version: 2026-10-19" \
-H "content-type: application/json" \
-d '{
"display_name": "Billing",
"metadata": {
"team": "ops"
}
}'const response = await fetch("https://core.thelittleworker.com/api/v1/password_sets", {
method: "POST",
headers: {
"x-api-key": process.env.LITTLE_WORKER_API_KEY,
"Little-Worker-Version": "2026-10-19",
"content-type": "application/json",
},
body: JSON.stringify({
display_name: "Billing",
metadata: {
team: "ops",
},
}),
})
const set = await response.json()import os
import requests
response = requests.post(
"https://core.thelittleworker.com/api/v1/password_sets",
headers={
"x-api-key": os.environ["LITTLE_WORKER_API_KEY"],
"Little-Worker-Version": "2026-10-19",
},
json={
"display_name": "Billing",
"metadata": {
"team": "ops",
},
},
)
set = response.json(){
"type": "password_set",
"id": "password_set_597a64d52e7f4e84ac5d95929bf4cbae",
"display_name": "Billing",
"metadata": {
"team": "ops"
},
"created_at": "2026-10-20T09:14:02.331Z",
"updated_at": "2026-10-20T09:14:02.331Z",
"archived_at": null,
"owner": null
}List password sets
GET/password_sets
List the sets you can see, newest first: the sets of the workspace that are not personal, every worker's own set, the shared set, and your personal sets. Other members' personal sets are left out, unless you are a workspace owner. Archived sets are left out unless you ask for them. The list ignores order and the created_at filters.
Query parameters
limitintegerHow many to answer, 1 to 100. The default is 20.pagestringThenext_pageof the answer before, to read the next page.include_archivedstringtruelists archived sets too.One of
true,false
Returns
A list: data holds the sets, and next_page is the page to send for the next ones (null on the last page).
Errors
| Status | Type | When |
|---|---|---|
| 400 | invalid_request_error | A filter is not valid, such as a limit outside 1 to 100 (error_code validation_error). page is not a page this list gave (error_code invalid_cursor). Read the first page again. |
| 401 | authentication_error | The key is missing, removed, or not a key. Send it in x-api-key. |
| 429 | rate_limit_error | The workspace made too many requests this minute. Wait the seconds in Retry-After, then try again. |
curl "https://core.thelittleworker.com/api/v1/password_sets?limit=10" \
-H "x-api-key: $LITTLE_WORKER_API_KEY" \
-H "Little-Worker-Version: 2026-10-19"const response = await fetch("https://core.thelittleworker.com/api/v1/password_sets?limit=10", {
headers: {
"x-api-key": process.env.LITTLE_WORKER_API_KEY,
"Little-Worker-Version": "2026-10-19",
},
})
const sets = await response.json()import os
import requests
response = requests.get(
"https://core.thelittleworker.com/api/v1/password_sets",
headers={
"x-api-key": os.environ["LITTLE_WORKER_API_KEY"],
"Little-Worker-Version": "2026-10-19",
},
params={
"limit": "10",
},
)
sets = response.json(){
"data": [
{
"type": "password_set",
"id": "password_set_597a64d52e7f4e84ac5d95929bf4cbae",
"display_name": "Billing",
"metadata": {
"team": "ops"
},
"created_at": "2026-10-20T09:14:02.331Z",
"updated_at": "2026-10-20T09:14:02.331Z",
"archived_at": null,
"owner": null
}
],
"next_page": null
}Read a password set
GET/password_sets/{password_set_id}
Read one set, archived or not.
Path parameters
password_set_idpassword set idRequiredThe password set, such aspassword_set_597a64d52e7f4e84ac5d95929bf4cbae.
Returns
The set.
Errors
| Status | Type | When |
|---|---|---|
| 400 | invalid_request_error | password_set_id is not a password set id. error_code is validation_error. |
| 401 | authentication_error | The key is missing, removed, or not a key. Send it in x-api-key. |
| 404 | not_found_error | No set in the workspace has this id, or it is another member's personal set (Password set not found.). A workspace owner sees every member's personal set. |
| 429 | rate_limit_error | The workspace made too many requests this minute. Wait the seconds in Retry-After, then try again. |
curl https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae \
-H "x-api-key: $LITTLE_WORKER_API_KEY" \
-H "Little-Worker-Version: 2026-10-19"const response = await fetch("https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae", {
headers: {
"x-api-key": process.env.LITTLE_WORKER_API_KEY,
"Little-Worker-Version": "2026-10-19",
},
})
const set = await response.json()import os
import requests
response = requests.get(
"https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae",
headers={
"x-api-key": os.environ["LITTLE_WORKER_API_KEY"],
"Little-Worker-Version": "2026-10-19",
},
)
set = response.json(){
"type": "password_set",
"id": "password_set_597a64d52e7f4e84ac5d95929bf4cbae",
"display_name": "Billing",
"metadata": {
"team": "ops"
},
"created_at": "2026-10-20T09:14:02.331Z",
"updated_at": "2026-10-20T09:14:02.331Z",
"archived_at": null,
"owner": null
}Change a password set
POST/password_sets/{password_set_id}
Change a set's name or labels. A field left out stays as it was. An archived set takes no change.
Path parameters
password_set_idpassword set idRequiredThe password set, such aspassword_set_597a64d52e7f4e84ac5d95929bf4cbae.
Body
display_namestringA new name, 1 to 255 characters.metadataobjectLabels to set on the set. A key with a string value is set, a key set tonullis removed, and keys left out stay. At most 16 keys remain.nullinstead of an object removes every label.
Returns
The set, changed.
Errors
| Status | Type | When |
|---|---|---|
| 400 | invalid_request_error | A field is not valid (error_code validation_error): password_set_id is not a password set id, display_name is empty or over 255 characters, a label breaks its limits, or the labels would pass 16. |
| 401 | authentication_error | The key is missing, removed, or not a key. Send it in x-api-key. |
| 404 | not_found_error | No set in the workspace has this id, or it is another member's personal set (Password set not found.). A workspace owner sees every member's personal set. |
| 409 | conflict_error | The set is archived and takes no change (This password set is archived and cannot change.). |
| 429 | rate_limit_error | The workspace made too many requests this minute. Wait the seconds in Retry-After, then try again. |
curl "https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae" \
-H "x-api-key: $LITTLE_WORKER_API_KEY" \
-H "Little-Worker-Version: 2026-10-19" \
-H "content-type: application/json" \
-d '{
"display_name": "Billing tools"
}'const response = await fetch("https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae", {
method: "POST",
headers: {
"x-api-key": process.env.LITTLE_WORKER_API_KEY,
"Little-Worker-Version": "2026-10-19",
"content-type": "application/json",
},
body: JSON.stringify({
display_name: "Billing tools",
}),
})
const set = await response.json()import os
import requests
response = requests.post(
"https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae",
headers={
"x-api-key": os.environ["LITTLE_WORKER_API_KEY"],
"Little-Worker-Version": "2026-10-19",
},
json={
"display_name": "Billing tools",
},
)
set = response.json(){
"type": "password_set",
"id": "password_set_597a64d52e7f4e84ac5d95929bf4cbae",
"display_name": "Billing tools",
"metadata": {
"team": "ops"
},
"created_at": "2026-10-20T09:14:02.331Z",
"updated_at": "2026-10-20T10:02:47.915Z",
"archived_at": null,
"owner": null
}Archive a password set
POST/password_sets/{password_set_id}/archive
Archive a set. Every value it holds is wiped at once, and its passwords are archived with it. The records stay. It cannot be undone. Every enabled routine that names the set in its password_set_ids is paused. Archiving a set twice changes nothing.
Path parameters
password_set_idpassword set idRequiredThe password set, such aspassword_set_597a64d52e7f4e84ac5d95929bf4cbae.
Returns
The set, with archived_at set.
Errors
| Status | Type | When |
|---|---|---|
| 400 | invalid_request_error | password_set_id is not a password set id. error_code is validation_error. |
| 401 | authentication_error | The key is missing, removed, or not a key. Send it in x-api-key. |
| 404 | not_found_error | No set in the workspace has this id, or it is another member's personal set (Password set not found.). A workspace owner sees every member's personal set. |
| 409 | conflict_error | The set is a worker's own (A worker's own password set cannot be archived; it goes with its worker.), or the workspace's shared set (The workspace's shared password set cannot be archived.). |
| 429 | rate_limit_error | The workspace made too many requests this minute. Wait the seconds in Retry-After, then try again. |
curl "https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/archive" \
-X POST \
-H "x-api-key: $LITTLE_WORKER_API_KEY" \
-H "Little-Worker-Version: 2026-10-19"const response = await fetch("https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/archive", {
method: "POST",
headers: {
"x-api-key": process.env.LITTLE_WORKER_API_KEY,
"Little-Worker-Version": "2026-10-19",
},
})
const set = await response.json()import os
import requests
response = requests.post(
"https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/archive",
headers={
"x-api-key": os.environ["LITTLE_WORKER_API_KEY"],
"Little-Worker-Version": "2026-10-19",
},
)
set = response.json(){
"type": "password_set",
"id": "password_set_597a64d52e7f4e84ac5d95929bf4cbae",
"display_name": "Billing",
"metadata": {
"team": "ops"
},
"created_at": "2026-10-20T09:14:02.331Z",
"updated_at": "2026-10-25T17:12:03.418Z",
"archived_at": "2026-10-25T17:12:03.418Z",
"owner": null
}Delete a password set
DEL/password_sets/{password_set_id}
Delete a set and every password in it. It cannot be undone. Every enabled routine that names the set in its password_set_ids is paused, and the set leaves its list.
Path parameters
password_set_idpassword set idRequiredThe password set, such aspassword_set_597a64d52e7f4e84ac5d95929bf4cbae.
Returns
type is password_set_deleted, with the set's id.
Errors
| Status | Type | When |
|---|---|---|
| 400 | invalid_request_error | password_set_id is not a password set id. error_code is validation_error. |
| 401 | authentication_error | The key is missing, removed, or not a key. Send it in x-api-key. |
| 404 | not_found_error | No set in the workspace has this id, or it is another member's personal set (Password set not found.). A workspace owner sees every member's personal set. |
| 409 | conflict_error | The set is a worker's own (A worker's own password set cannot be deleted; it goes with its worker.), or the workspace's shared set (The workspace's shared password set cannot be deleted.). |
| 429 | rate_limit_error | The workspace made too many requests this minute. Wait the seconds in Retry-After, then try again. |
curl "https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae" \
-X DELETE \
-H "x-api-key: $LITTLE_WORKER_API_KEY" \
-H "Little-Worker-Version: 2026-10-19"const response = await fetch("https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae", {
method: "DELETE",
headers: {
"x-api-key": process.env.LITTLE_WORKER_API_KEY,
"Little-Worker-Version": "2026-10-19",
},
})
const deleted = await response.json()import os
import requests
response = requests.delete(
"https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae",
headers={
"x-api-key": os.environ["LITTLE_WORKER_API_KEY"],
"Little-Worker-Version": "2026-10-19",
},
)
deleted = response.json(){
"type": "password_set_deleted",
"id": "password_set_597a64d52e7f4e84ac5d95929bf4cbae"
}Save a password
POST/password_sets/{password_set_id}/passwords
Save a password in a set. Its auth says what kind it is and holds the value. The value is sealed on arrival, and the answer never shows it.
A new password is always if your key was made with Can allow actions, and ask for any other key. Only a key that can allow actions may set always. The first use of an ask password in a task waits for a person's Allow.
A set holds up to 256 passwords. The count leaves out archived passwords, except in a worker's own set, where an archived password still counts and still holds its name.
Path parameters
password_set_idpassword set idRequiredThe password set, such aspassword_set_597a64d52e7f4e84ac5d95929bf4cbae.
Body
authobjectRequiredWhat to save. Send the fields of itstype, as the table of kinds says.Show its 10 fields
typestringRequiredenvironment_variablesaves a value a command uses under a name.mcp_oauthsaves an app sign-in that Little Worker refreshes.static_bearersaves a fixed token for an app, such as an API key.One of
environment_variable,mcp_oauth,static_bearersecret_namestringRequired forenvironment_variable. The name a command uses: 1 to 255 letters, digits and_, not starting with a digit. A name the computer uses is refused, whatever its case:PATHandhttps_proxyare two, and so is any name startingLD_,CURSOR_,CLOUD_AGENT_orSAND_.secret_valuestringRequired forenvironment_variable. The value, 8 to 4,096 characters. It is sealed on arrival and no route answers it.networkingobjectRequired forenvironment_variable. The websites the value may be sent to, as{ "type": "limited", "allowed_hosts": [...] }.Show its 2 fields
typestringRequiredAlwayslimited.allowed_hostsarray of stringsRequired1 to 16 websites, each once: a lowercase name such asapi.example.com, a*.example.comwildcard that covers its subdomains but notexample.comitself, or a public IPv4 address. Private and special addresses are refused, and so is a wildcard over a shared host. A value goes to an IPv4 address only when the website's certificate lists it.
injection_locationobjectForenvironment_variable. Where the real value may go in a request.headerandbodyare each on or off. A field left out is off, and both off is refused. Left out whole, it is the header only.Show its 2 fields
headerbooleanWhether the value may go in a request's headers.bodybooleanWhether the value may go in a request's body and address.
app_urlstringRequired formcp_oauthandstatic_bearer. The address of the app, anhttpsaddress of up to 2,048 characters. It cannot change later.tokenstringRequired forstatic_bearer. The fixed token, 1 to 8,192 characters. Little Worker sends it to the app asAuthorization: Bearer.access_tokenstringRequired formcp_oauth. The access token, 1 to 16,384 characters.expires_attimeFormcp_oauth. When the access token expires, as an RFC 3339 time in UTC ending inZ. Little Worker refreshes the token when it is close. Left out ornull, it uses the token as it is and never refreshes it.refreshobjectFormcp_oauth. How Little Worker gets a new access token. Without it, the sign-in works until the token expires.nullis the same as leaving it out.Show its 6 fields
client_idstringRequiredThe client that signs in at the token endpoint, 1 to 16,384 characters. It cannot change later.refresh_tokenstringRequiredThe refresh token, 1 to 16,384 characters.token_endpointstringRequiredThehttpsaddress where Little Worker asks for a new access token, up to 2,048 characters. It cannot change later.token_endpoint_authobjectRequiredHow Little Worker signs in at the token endpoint:{ "type": "none" }, or{ "type": "client_secret_basic", "client_secret" }, or{ "type": "client_secret_post", "client_secret" }. A client secret is 1 to 16,384 characters.resourcestringThe resource the token is for, up to 2,048 characters.scopestringThe scope the token is for, up to 2,048 characters.
display_namestringA name for the password, up to 255 characters. Left out ornull, the password has none.metadataobjectYour own labels for the password: up to 16 keys of 1 to 64 characters, each with a string value of up to 512.permissionstringalwaysuses the password without asking.askwaits for a person's Allow on its first use in a task. Left out, it isalwaysfor a key that can allow actions, andaskfor any other key.One of
ask,always
Returns
200 and the password. It never holds a value.
typestringAlwayspassword.idpassword idThe password's id:password_and 32 hex digits.password_set_idpassword set idThe set the password is in.display_namestring or nullThe password's name as a person reads it, up to 255 characters.nullwhen it has none.metadataobjectYour own labels for the password: up to 16 keys of 1 to 64 characters, each with a string value of up to 512.authobjectWhat the password is and where it may go. A value, a token or a client secret is never in it. Itstypedecides the other fields.Show its 7 fields
typestringenvironment_variableis a value a command uses under a name.mcp_oauthis an app sign-in.static_beareris a fixed token for an app.One of
environment_variable,mcp_oauth,static_bearersecret_namestringOnly onenvironment_variable: the name a command uses.networkingobjectOnly onenvironment_variable: the websites the value may be sent to, as{ "type": "limited", "allowed_hosts": [...] }.injection_locationobjectOnly onenvironment_variable: where the value may go in a request, as{ "header": true, "body": false }.app_urlstringOnly onmcp_oauthandstatic_bearer: the address of the app the sign-in is for, in its plain form: a lowercase scheme and host, no default port and no trailing slash.expires_attime or nullOnly onmcp_oauth: when the access token expires.nullwhen it does not say.refreshobject or nullOnly onmcp_oauth: how Little Worker gets a new access token, without the refresh token and the client secret.nullwhen the sign-in has no refresh settings.Show its 5 fields
client_idstringThe client that signs in at the token endpoint.token_endpointstringThe address Little Worker asks for a new access token.token_endpoint_authobjectHow Little Worker signs in at the token endpoint:{ "type" }isnone,client_secret_basicorclient_secret_post.resourcestring or nullThe resource the token is for, if one was given.scopestring or nullThe scope the token is for, if one was given.
permissionstringalwayslets a task use the password without asking.askwaits for a person's Allow the first time a task uses it (see Approvals).One of
ask,alwayscreated_attimeWhen the password was saved.updated_attimeWhen the password last changed.archived_attime or nullWhen the password was archived, and its value wiped.nullwhile it is not.
Errors
| Status | Type | When |
|---|---|---|
| 400 | invalid_request_error | A field is not valid (error_code validation_error): a name, value, website, address or label that breaks its rule, a field its type needs is missing or one it does not take is sent, both injection_location fields off, the set already holds 256 passwords, or an app sign-in is saved in a worker's own set (message says which). |
| 401 | authentication_error | The key is missing, removed, or not a key. Send it in x-api-key. |
| 403 | permission_error | permission is always, and the key was not made with Can allow actions (error_code person_required). Make a key with Can allow actions on. |
| 404 | not_found_error | No set in the workspace has this id, or it is another member's personal set (Password set not found.). A workspace owner sees every member's personal set. |
| 409 | conflict_error | The set is archived (This password set is archived; it takes no new passwords.), already has a password with this secret_name, or already has a sign-in for this app_url (the address in its plain form). Pick another name, or change the password that is there. |
| 429 | rate_limit_error | The workspace made too many requests this minute. Wait the seconds in Retry-After, then try again. |
curl "https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/passwords" \
-H "x-api-key: $LITTLE_WORKER_API_KEY" \
-H "Little-Worker-Version: 2026-10-19" \
-H "content-type: application/json" \
-d '{
"display_name": "Billing API key",
"auth": {
"type": "environment_variable",
"secret_name": "BILLING_API_KEY",
"secret_value": "replace-with-the-real-key",
"networking": {
"type": "limited",
"allowed_hosts": [
"api.billing.example.com"
]
}
},
"permission": "ask"
}'const response = await fetch("https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/passwords", {
method: "POST",
headers: {
"x-api-key": process.env.LITTLE_WORKER_API_KEY,
"Little-Worker-Version": "2026-10-19",
"content-type": "application/json",
},
body: JSON.stringify({
display_name: "Billing API key",
auth: {
type: "environment_variable",
secret_name: "BILLING_API_KEY",
secret_value: "replace-with-the-real-key",
networking: {
type: "limited",
allowed_hosts: [
"api.billing.example.com",
],
},
},
permission: "ask",
}),
})
const password = await response.json()import os
import requests
response = requests.post(
"https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/passwords",
headers={
"x-api-key": os.environ["LITTLE_WORKER_API_KEY"],
"Little-Worker-Version": "2026-10-19",
},
json={
"display_name": "Billing API key",
"auth": {
"type": "environment_variable",
"secret_name": "BILLING_API_KEY",
"secret_value": "replace-with-the-real-key",
"networking": {
"type": "limited",
"allowed_hosts": [
"api.billing.example.com",
],
},
},
"permission": "ask",
},
)
password = response.json(){
"type": "password",
"id": "password_0e4b8d2f6a1c4e7a9b3d5f7c1a2e8b46",
"password_set_id": "password_set_597a64d52e7f4e84ac5d95929bf4cbae",
"display_name": "Billing API key",
"metadata": {},
"auth": {
"type": "environment_variable",
"secret_name": "BILLING_API_KEY",
"networking": {
"type": "limited",
"allowed_hosts": [
"api.billing.example.com"
]
},
"injection_location": {
"header": true,
"body": false
}
},
"permission": "ask",
"created_at": "2026-10-20T09:31:55.208Z",
"updated_at": "2026-10-20T09:31:55.208Z",
"archived_at": null
}List passwords
GET/password_sets/{password_set_id}/passwords
List the passwords in a set, newest first. Archived passwords are left out unless you ask for them. The list ignores order and the created_at filters. An app sign-in made in the app, which keeps its tokens there, is not listed.
Path parameters
password_set_idpassword set idRequiredThe password set, such aspassword_set_597a64d52e7f4e84ac5d95929bf4cbae.
Query parameters
limitintegerHow many to answer, 1 to 100. The default is 20.pagestringThenext_pageof the answer before, to read the next page.include_archivedstringtruelists archived passwords too.One of
true,false
Returns
A list: data holds the passwords, as Save a password shows them, and next_page is the page to send for the next ones (null on the last page).
Errors
| Status | Type | When |
|---|---|---|
| 400 | invalid_request_error | A filter is not valid, such as a limit outside 1 to 100 (error_code validation_error). page is not a page this list gave (error_code invalid_cursor). Read the first page again. |
| 401 | authentication_error | The key is missing, removed, or not a key. Send it in x-api-key. |
| 404 | not_found_error | No set in the workspace has this id, or it is another member's personal set (Password set not found.). A workspace owner sees every member's personal set. |
| 429 | rate_limit_error | The workspace made too many requests this minute. Wait the seconds in Retry-After, then try again. |
curl https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/passwords \
-H "x-api-key: $LITTLE_WORKER_API_KEY" \
-H "Little-Worker-Version: 2026-10-19"const response = await fetch("https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/passwords", {
headers: {
"x-api-key": process.env.LITTLE_WORKER_API_KEY,
"Little-Worker-Version": "2026-10-19",
},
})
const passwords = await response.json()import os
import requests
response = requests.get(
"https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/passwords",
headers={
"x-api-key": os.environ["LITTLE_WORKER_API_KEY"],
"Little-Worker-Version": "2026-10-19",
},
)
passwords = response.json(){
"data": [
{
"type": "password",
"id": "password_0e4b8d2f6a1c4e7a9b3d5f7c1a2e8b46",
"password_set_id": "password_set_597a64d52e7f4e84ac5d95929bf4cbae",
"display_name": "Billing API key",
"metadata": {},
"auth": {
"type": "environment_variable",
"secret_name": "BILLING_API_KEY",
"networking": {
"type": "limited",
"allowed_hosts": [
"api.billing.example.com"
]
},
"injection_location": {
"header": true,
"body": false
}
},
"permission": "ask",
"created_at": "2026-10-20T09:31:55.208Z",
"updated_at": "2026-10-20T09:31:55.208Z",
"archived_at": null
}
],
"next_page": null
}Read a password
GET/password_sets/{password_set_id}/passwords/{password_id}
Read one password. The answer shows where it may go, never its value.
Path parameters
password_set_idpassword set idRequiredThe password set, such aspassword_set_597a64d52e7f4e84ac5d95929bf4cbae.password_idpassword idRequiredThe password, such aspassword_0e4b8d2f6a1c4e7a9b3d5f7c1a2e8b46.
Returns
The password, as Save a password shows it.
Errors
| Status | Type | When |
|---|---|---|
| 400 | invalid_request_error | password_set_id or password_id is not an id of its kind. error_code is validation_error. |
| 401 | authentication_error | The key is missing, removed, or not a key. Send it in x-api-key. |
| 404 | not_found_error | No set you can see has this password_set_id (Password set not found.), or the set has no password with this password_id (Password not found.). |
| 429 | rate_limit_error | The workspace made too many requests this minute. Wait the seconds in Retry-After, then try again. |
curl https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/passwords/password_0e4b8d2f6a1c4e7a9b3d5f7c1a2e8b46 \
-H "x-api-key: $LITTLE_WORKER_API_KEY" \
-H "Little-Worker-Version: 2026-10-19"const response = await fetch("https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/passwords/password_0e4b8d2f6a1c4e7a9b3d5f7c1a2e8b46", {
headers: {
"x-api-key": process.env.LITTLE_WORKER_API_KEY,
"Little-Worker-Version": "2026-10-19",
},
})
const password = await response.json()import os
import requests
response = requests.get(
"https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/passwords/password_0e4b8d2f6a1c4e7a9b3d5f7c1a2e8b46",
headers={
"x-api-key": os.environ["LITTLE_WORKER_API_KEY"],
"Little-Worker-Version": "2026-10-19",
},
)
password = response.json(){
"type": "password",
"id": "password_0e4b8d2f6a1c4e7a9b3d5f7c1a2e8b46",
"password_set_id": "password_set_597a64d52e7f4e84ac5d95929bf4cbae",
"display_name": "Billing API key",
"metadata": {},
"auth": {
"type": "environment_variable",
"secret_name": "BILLING_API_KEY",
"networking": {
"type": "limited",
"allowed_hosts": [
"api.billing.example.com"
]
},
"injection_location": {
"header": true,
"body": false
}
},
"permission": "ask",
"created_at": "2026-10-20T09:31:55.208Z",
"updated_at": "2026-10-20T09:31:55.208Z",
"archived_at": null
}Change a password
POST/password_sets/{password_set_id}/passwords/{password_id}
Change a password's value, where it may go, its name, its labels or its permission. A field left out stays as it was. Send auth with the password's own type. A task at work reads an environment_variable password for each command, so its next command uses the change.
A change through the API to the websites or the places of an environment_variable password sets its permission back to ask, so its next use waits for a person. Send permission in the same change to set it again, which takes a key that can allow actions. Only a person, in the app, may loosen a password saved in the app.
Path parameters
password_set_idpassword set idRequiredThe password set, such aspassword_set_597a64d52e7f4e84ac5d95929bf4cbae.password_idpassword idRequiredThe password, such aspassword_0e4b8d2f6a1c4e7a9b3d5f7c1a2e8b46.
Body
authobjectThe changes to the value and where it goes. Itstypemust be the password's own.Show its 8 fields
typestringRequiredThe password's ownauth.type. It cannot change, and neither cansecret_name.One of
environment_variable,mcp_oauth,static_bearersecret_valuestringForenvironment_variable. A new value, 8 to 4,096 characters.networkingobjectForenvironment_variable. A new{ "type": "limited", "allowed_hosts": [...] }, which replaces the old websites.allowed_hostsholds 1 to 16 websites, each once: a lowercase name such asapi.example.com, a*.example.comwildcard that covers its subdomains but notexample.comitself, or a public IPv4 address. Private and special addresses are refused, and so is a wildcard over a shared host. A value goes to an IPv4 address only when the website's certificate lists it.injection_locationobjectForenvironment_variable. Where the real value may go in a request. Sendheader,bodyor both: each field you send replaces that one, and a field you leave out stays. Both off is refused.tokenstringForstatic_bearer. A new token, 1 to 8,192 characters.app_urlcannot change.access_tokenstringFormcp_oauth. A new access token, 1 to 16,384 characters.expires_attimeFormcp_oauth. When the access token expires, as an RFC 3339 time in UTC ending inZ. Left out, the old time stays.nullremoves it.refreshobjectFormcp_oauth. Changes to the refresh settings: a newrefresh_token, a newscope(nullremoves it), and a newtoken_endpoint_authofclient_secret_basicorclient_secret_post, with a newclient_secretunless the sign-in already holds one.nullremoves the refresh settings with their refresh token and client secret. A sign-in saved with no refresh settings cannot get them in a change: the call is refused.client_id,token_endpointandresourcecannot change, and a sign-in cannot move tonone.
display_namestringA new name, up to 255 characters.nullremoves the name.metadataobjectLabels to set on the password. A key with a string value is set, a key set tonullis removed, and keys left out stay. At most 16 keys remain.nullinstead of an object removes every label.permissionstringaskoralways. Any key may setask.alwaystakes a key made with Can allow actions.One of
ask,always
Returns
The password, as Save a password shows it.
Errors
| Status | Type | When |
|---|---|---|
| 400 | invalid_request_error | A field is not valid (error_code validation_error): an id is not of its kind, auth.type is not the password's own, a value, website or label breaks its rule, both injection_location fields would be off, the labels would pass 16, a refresh is sent for a sign-in with no refresh settings, or a new token_endpoint_auth has no client_secret and the sign-in holds none (message says which). |
| 401 | authentication_error | The key is missing, removed, or not a key. Send it in x-api-key. |
| 403 | permission_error | The change sets permission to always where it is not always now (error_code person_required). Either the key was not made with Can allow actions: make a key with it on. Or the password was saved in the app: only a person can loosen it, in the app, whatever the key. |
| 404 | not_found_error | No set you can see has this password_set_id (Password set not found.), or the set has no password with this password_id (Password not found.). |
| 409 | conflict_error | The password is archived and cannot change (This password is archived and cannot change.). Every password of an archived set is archived. Or an mcp_oauth sign-in's tokens cannot be read (This sign-in's tokens cannot be read; delete it and save it again.). |
| 429 | rate_limit_error | The workspace made too many requests this minute. Wait the seconds in Retry-After, then try again. |
curl "https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/passwords/password_0e4b8d2f6a1c4e7a9b3d5f7c1a2e8b46" \
-H "x-api-key: $LITTLE_WORKER_API_KEY" \
-H "Little-Worker-Version: 2026-10-19" \
-H "content-type: application/json" \
-d '{
"auth": {
"type": "environment_variable",
"secret_value": "replace-with-the-new-key"
}
}'const response = await fetch("https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/passwords/password_0e4b8d2f6a1c4e7a9b3d5f7c1a2e8b46", {
method: "POST",
headers: {
"x-api-key": process.env.LITTLE_WORKER_API_KEY,
"Little-Worker-Version": "2026-10-19",
"content-type": "application/json",
},
body: JSON.stringify({
auth: {
type: "environment_variable",
secret_value: "replace-with-the-new-key",
},
}),
})
const password = await response.json()import os
import requests
response = requests.post(
"https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/passwords/password_0e4b8d2f6a1c4e7a9b3d5f7c1a2e8b46",
headers={
"x-api-key": os.environ["LITTLE_WORKER_API_KEY"],
"Little-Worker-Version": "2026-10-19",
},
json={
"auth": {
"type": "environment_variable",
"secret_value": "replace-with-the-new-key",
},
},
)
password = response.json(){
"type": "password",
"id": "password_0e4b8d2f6a1c4e7a9b3d5f7c1a2e8b46",
"password_set_id": "password_set_597a64d52e7f4e84ac5d95929bf4cbae",
"display_name": "Billing API key",
"metadata": {},
"auth": {
"type": "environment_variable",
"secret_name": "BILLING_API_KEY",
"networking": {
"type": "limited",
"allowed_hosts": [
"api.billing.example.com"
]
},
"injection_location": {
"header": true,
"body": false
}
},
"permission": "ask",
"created_at": "2026-10-20T09:31:55.208Z",
"updated_at": "2026-10-20T11:40:09.562Z",
"archived_at": null
}Archive a password
POST/password_sets/{password_set_id}/passwords/{password_id}/archive
Archive a password. Its value is wiped at once and its record stays, so a task cannot use it again. No route brings it back. Archiving a password twice changes nothing.
Path parameters
password_set_idpassword set idRequiredThe password set, such aspassword_set_597a64d52e7f4e84ac5d95929bf4cbae.password_idpassword idRequiredThe password, such aspassword_0e4b8d2f6a1c4e7a9b3d5f7c1a2e8b46.
Returns
The password, as Save a password shows it, with archived_at set.
Errors
| Status | Type | When |
|---|---|---|
| 400 | invalid_request_error | password_set_id or password_id is not an id of its kind. error_code is validation_error. |
| 401 | authentication_error | The key is missing, removed, or not a key. Send it in x-api-key. |
| 404 | not_found_error | No set you can see has this password_set_id (Password set not found.), or the set has no password with this password_id (Password not found.). |
| 429 | rate_limit_error | The workspace made too many requests this minute. Wait the seconds in Retry-After, then try again. |
curl "https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/passwords/password_0e4b8d2f6a1c4e7a9b3d5f7c1a2e8b46/archive" \
-X POST \
-H "x-api-key: $LITTLE_WORKER_API_KEY" \
-H "Little-Worker-Version: 2026-10-19"const response = await fetch("https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/passwords/password_0e4b8d2f6a1c4e7a9b3d5f7c1a2e8b46/archive", {
method: "POST",
headers: {
"x-api-key": process.env.LITTLE_WORKER_API_KEY,
"Little-Worker-Version": "2026-10-19",
},
})
const password = await response.json()import os
import requests
response = requests.post(
"https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/passwords/password_0e4b8d2f6a1c4e7a9b3d5f7c1a2e8b46/archive",
headers={
"x-api-key": os.environ["LITTLE_WORKER_API_KEY"],
"Little-Worker-Version": "2026-10-19",
},
)
password = response.json(){
"type": "password",
"id": "password_0e4b8d2f6a1c4e7a9b3d5f7c1a2e8b46",
"password_set_id": "password_set_597a64d52e7f4e84ac5d95929bf4cbae",
"display_name": "Billing API key",
"metadata": {},
"auth": {
"type": "environment_variable",
"secret_name": "BILLING_API_KEY",
"networking": {
"type": "limited",
"allowed_hosts": [
"api.billing.example.com"
]
},
"injection_location": {
"header": true,
"body": false
}
},
"permission": "ask",
"created_at": "2026-10-20T09:31:55.208Z",
"updated_at": "2026-10-25T17:12:03.418Z",
"archived_at": "2026-10-25T17:12:03.418Z"
}Delete a password
DEL/password_sets/{password_set_id}/passwords/{password_id}
Delete a password and its record. A task cannot use it again.
Path parameters
password_set_idpassword set idRequiredThe password set, such aspassword_set_597a64d52e7f4e84ac5d95929bf4cbae.password_idpassword idRequiredThe password, such aspassword_0e4b8d2f6a1c4e7a9b3d5f7c1a2e8b46.
Returns
type is password_deleted, with the password's id.
Errors
| Status | Type | When |
|---|---|---|
| 400 | invalid_request_error | password_set_id or password_id is not an id of its kind. error_code is validation_error. |
| 401 | authentication_error | The key is missing, removed, or not a key. Send it in x-api-key. |
| 404 | not_found_error | No set you can see has this password_set_id (Password set not found.), or the set has no password with this password_id (Password not found.). |
| 429 | rate_limit_error | The workspace made too many requests this minute. Wait the seconds in Retry-After, then try again. |
curl "https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/passwords/password_0e4b8d2f6a1c4e7a9b3d5f7c1a2e8b46" \
-X DELETE \
-H "x-api-key: $LITTLE_WORKER_API_KEY" \
-H "Little-Worker-Version: 2026-10-19"const response = await fetch("https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/passwords/password_0e4b8d2f6a1c4e7a9b3d5f7c1a2e8b46", {
method: "DELETE",
headers: {
"x-api-key": process.env.LITTLE_WORKER_API_KEY,
"Little-Worker-Version": "2026-10-19",
},
})
const deleted = await response.json()import os
import requests
response = requests.delete(
"https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/passwords/password_0e4b8d2f6a1c4e7a9b3d5f7c1a2e8b46",
headers={
"x-api-key": os.environ["LITTLE_WORKER_API_KEY"],
"Little-Worker-Version": "2026-10-19",
},
)
deleted = response.json(){
"type": "password_deleted",
"id": "password_0e4b8d2f6a1c4e7a9b3d5f7c1a2e8b46"
}Check an app sign-in
POST/password_sets/{password_set_id}/passwords/{password_id}/mcp_oauth_validate
Check that an mcp_oauth sign-in still works. Little Worker sends the app an MCP initialize call with the token. If the app refuses it (401 or 403), it tries the refresh token once, keeps the new tokens if that works, and sends the call again. The answer says how it went, and keeps the app's answers with every secret masked. A static_bearer or environment_variable password cannot be checked.
Path parameters
password_set_idpassword set idRequiredThe password set, such aspassword_set_597a64d52e7f4e84ac5d95929bf4cbae.password_idpassword idRequiredThe password, such aspassword_0e4b8d2f6a1c4e7a9b3d5f7c1a2e8b46.
Returns
type is password_validation, with these fields.
typestringAlwayspassword_validation.password_idpassword idThe password that was checked.password_set_idpassword set idIts set.statusstringvalidwhen the app took a token, after a refresh if it needed one.invalidwhen the app refused the token with401or403and no refresh fixed it.unknownwhen the app or the token endpoint could not be reached, or answered something else.One of
valid,invalid,unknownhas_refresh_tokenbooleanWhether the sign-in has a refresh token and the settings to use it.validated_attimeWhen the check ran.mcp_probeobject or nullThe failing step: the app'sinitializecall and the answer kept.nullwhen the app took the token.Show its 2 fields
methodstringThe MCP method Little Worker called.http_responseobject or nullThe app's answer.nullwhen the app was not reached.Show its 4 fields
status_codeintegerThe HTTP status the server answered.content_typestringThe answer's content type.bodystringThe first 2,048 characters of the answer's body, with every secret of the sign-in masked.body_truncatedbooleantruewhen the body is not the whole answer.
refreshobject or nullWhat came of the refresh Little Worker made after the app refused the token with401or403.nullwhen the app did not refuse it so.Show its 2 fields
statusstringHow the refresh went.succeeded: the token endpoint gave a new token.failed: it answered and refused.connect_error: it could not be reached or gave no token.no_refresh_token: the sign-in has no refresh token or no refresh settings, so none was tried.One of
succeeded,failed,connect_error,no_refresh_tokenhttp_responseobject or nullThe token endpoint's answer.nullunless it answered and refused.Show its 4 fields
status_codeintegerThe HTTP status the server answered.content_typestringThe answer's content type.bodystringThe first 2,048 characters of the answer's body, with every secret of the sign-in masked.body_truncatedbooleantruewhen the body is not the whole answer.
Errors
| Status | Type | When |
|---|---|---|
| 400 | invalid_request_error | The password is not an mcp_oauth sign-in (Only an mcp_oauth password can be checked.), or an id is not of its kind (error_code validation_error). |
| 401 | authentication_error | The key is missing, removed, or not a key. Send it in x-api-key. |
| 404 | not_found_error | No set you can see has this password_set_id (Password set not found.), or the set has no password with this password_id (Password not found.). |
| 409 | conflict_error | The password is archived (This password is archived and cannot change.), or its tokens cannot be read (This sign-in's tokens cannot be read; delete it and save it again.). |
| 429 | rate_limit_error | The workspace made too many requests this minute. Wait the seconds in Retry-After, then try again. |
curl "https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/passwords/password_6c2a8e4f0b1d4a7e9c3b5d7f1a4e2c80/mcp_oauth_validate" \
-X POST \
-H "x-api-key: $LITTLE_WORKER_API_KEY" \
-H "Little-Worker-Version: 2026-10-19"const response = await fetch("https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/passwords/password_6c2a8e4f0b1d4a7e9c3b5d7f1a4e2c80/mcp_oauth_validate", {
method: "POST",
headers: {
"x-api-key": process.env.LITTLE_WORKER_API_KEY,
"Little-Worker-Version": "2026-10-19",
},
})
const check = await response.json()import os
import requests
response = requests.post(
"https://core.thelittleworker.com/api/v1/password_sets/password_set_597a64d52e7f4e84ac5d95929bf4cbae/passwords/password_6c2a8e4f0b1d4a7e9c3b5d7f1a4e2c80/mcp_oauth_validate",
headers={
"x-api-key": os.environ["LITTLE_WORKER_API_KEY"],
"Little-Worker-Version": "2026-10-19",
},
)
check = response.json(){
"type": "password_validation",
"password_id": "password_6c2a8e4f0b1d4a7e9c3b5d7f1a4e2c80",
"password_set_id": "password_set_597a64d52e7f4e84ac5d95929bf4cbae",
"status": "valid",
"has_refresh_token": true,
"validated_at": "2026-10-25T17:20:41.073Z",
"mcp_probe": null,
"refresh": null
}