PATCH Rename or Rotate Source
Rename a connected source, replace its stored credential, or both — without breaking the identities bound to it
https://api.anakin.io/v1/wire/identity-sources/{id}Renames a connected source, rotates its stored credential, or both in one call.
Rotation preserves the row. The source ID never changes, so every identity bound to it keeps working. Disconnecting and reconnecting instead would null those bindings and force you to re-bind each identity by hand — this endpoint exists so a routine secret rotation isn't that.
A replacement credential is re-verified by exactly the code that admitted the original, and only replaces the working one on success. A rejected rotation leaves the existing credential untouched — a fat-fingered token can't brick a live connection.
Requires an X-API-Key; the source must belong to the authenticated user.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id required | string (UUID) | Identity source ID |
Request Body
Send display_name, provider credential fields, or both. Sending neither is an error.
| Parameter | Type | Description |
|---|---|---|
display_name | string | New label. Cannot be blank — omit the key entirely to leave the name alone |
auth_method | string | Which method to rotate with. Defaults to the method the source was connected with (config.auth_method) |
| provider fields | string | The full field set for the chosen method, same as connect. Present fields trigger a rotation |
Rename only:
{ "display_name": "Engineering vault (prod)" }Rotate a 1Password token:
{ "token": "ops_new_service_account_token" }Rotate an Azure client secret — the whole method field set, not just the changed value:
{
"tenant_id": "00000000-0000-0000-0000-000000000000",
"client_id": "00000000-0000-0000-0000-000000000000",
"client_secret": "the_new_secret",
"vault_urls": "https://my-vault.vault.azure.net"
}Rotation re-activates a revoked source. If the source flipped to
revokedbecause the provider rejected the old credential, a successful rotation returns it toactivewith its identity bindings intact.
Response
200 OK{
"status": "ok",
"identity_source": {
"id": "f1e2d3c4-0000-0000-0000-000000000000",
"user_id": "8a7b6c5d-0000-0000-0000-000000000000",
"provider": "1password",
"display_name": "Engineering vault (prod)",
"config": { "auth_method": "service_account" },
"scope_metadata": { "vaults": [ { "id": "abcd1234", "name": "Engineering" } ] },
"status": "active",
"last_verified_at": "2026-06-09T11:00:00Z",
"created_at": "2026-06-01T09:00:00Z",
"updated_at": "2026-06-09T11:00:00Z"
}
}The refreshed row, same shape as GET /v1/wire/identity-sources/{id}. A rotation also refreshes scope_metadata and bumps last_verified_at, since the new credential was just proven against the provider.
Error Responses
| Code | HTTP | When |
|---|---|---|
INVALID_BODY | 400 | Body isn't a JSON object, or a field's value isn't a string |
INVALID_INPUT | 400 | Neither display_name nor credential fields supplied, or display_name is blank |
NOT_FOUND | 404 | No source with that ID |
FORBIDDEN | 403 | The source belongs to another user |
UNSUPPORTED_PROVIDER | 400 | This engine has no source registered for the row's provider |
UNSUPPORTED_AUTH_METHOD | 400 | The provider doesn't offer that auth_method |
UNKNOWN_CONNECT_FIELD | 400 | A field name the chosen method doesn't declare |
INVALID_TOKEN_FORMAT | 400 | (1Password) The replacement token doesn't start with ops_ |
INVALID_VAULT_URL | 400 | (Azure) A vault_urls entry is malformed, or no Key Vault exists at it |
SOURCE_TOKEN_REJECTED | 400 | The provider rejected the replacement credential |
SOURCE_FORBIDDEN | 400 | The replacement authenticates but can't read a requested vault |
SOURCE_THROTTLED | 429 | The provider is rate-limiting us. Retry shortly |
SOURCE_VERIFY_FAILED | 400 | Could not reach the provider to verify. Retry in a moment |
SOURCE_NOT_AVAILABLE | 503 | The source resolver isn't configured on this engine |
Every rotation failure above is non-destructive — the stored credential is unchanged and the source keeps its previous status.
Code Examples
# rename only
curl https://api.anakin.io/v1/wire/identity-sources/f1e2d3c4-0000-0000-0000-000000000000 \
-X PATCH \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{ "display_name": "Engineering vault (prod)" }'
# rotate the credential
curl https://api.anakin.io/v1/wire/identity-sources/f1e2d3c4-0000-0000-0000-000000000000 \
-X PATCH \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{ "token": "ops_new_service_account_token" }'import requests
source_id = 'f1e2d3c4-0000-0000-0000-000000000000'
response = requests.patch(
f'https://api.anakin.io/v1/wire/identity-sources/{source_id}',
headers={'X-API-Key': 'your_api_key'},
json={'token': 'ops_new_service_account_token'},
)
data = response.json()
if data['status'] == 'ok':
print(f"Rotated — status is now {data['identity_source']['status']}")
else:
# The old credential is still in place.
print(f"Rotation rejected: {data['error']['code']} — {data['error']['message']}")const sourceId = 'f1e2d3c4-0000-0000-0000-000000000000';
const response = await fetch(`https://api.anakin.io/v1/wire/identity-sources/${sourceId}`, {
method: 'PATCH',
headers: {
'X-API-Key': 'your_api_key',
'Content-Type': 'application/json',
},
body: JSON.stringify({ token: 'ops_new_service_account_token' }),
});
const data = await response.json();
if (data.status === 'ok') {
console.log(`Rotated — status is now ${data.identity_source.status}`);
} else {
// The old credential is still in place.
console.error(`Rotation rejected: ${data.error.code} — ${data.error.message}`);
}Rate limit
20 requests per minute per user.
Related
- GET /v1/wire/identity-sources/providers — the field set for each auth method
- POST /v1/wire/identity-sources/{id}/verify — check the current credential without replacing it
- DELETE /v1/wire/identity-sources/{id} — disconnect instead