Skip to content

Credentials API

Credentials are envelope-encrypted at rest. The plaintext is never returned from any API call — list endpoints expose metadata only.

POST /credentials

Terminal window
curl -s -X POST "$API_URL/credentials" \
-H "Authorization: Bearer $SYNTHUSERS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"label": "Vercel staging signup",
"target_host": "vercel.com",
"username": "[email protected]",
"password": "<plaintext>"
}'

Response

{ "id": "cred_01H...", "label": "Vercel staging signup", "target_host": "vercel.com" }

target_host is the SSRF allowlist key. A run that references this credential must have a target_url whose host equals target_host.

GET /credentials

{
"items": [
{
"id": "cred_01H...",
"label": "Vercel staging signup",
"target_host": "vercel.com",
"username": "[email protected]",
"created_at": "2026-05-15T18:00:00Z"
}
]
}

No password, no encrypted blobs.

DELETE /credentials/:id

Hard-delete. Subsequent runs referencing this id return 404 credential_not_found.

Encryption model

  • Master key: 32 random bytes in Workers Secrets (MASTER_ENCRYPTION_KEY).
  • Per-customer DEK: random 32 bytes per customer, wrapped with the master.
  • Credential blob: AES-GCM over the password with the customer’s DEK.
  • In-transit: TLS 1.3 only.
  • At rest in D1: only encrypted_password + encrypted_dek bytes; never plaintext.
  • In the agent: decrypted once inside the SessionDO, passed to the browser action that needs it, then dropped.

The master key can be rotated with zero downtime by re-wrapping each customer’s data key.