Skip to content
Get Started

TOTP (Authenticator)

Store TOTP secrets and generate 2FA codes via API — no phone-based authenticator app required for your agents

The TOTP API lets you store encrypted TOTP secrets and generate 2FA codes programmatically. Instead of requiring an AI agent or automation to use a phone-based authenticator app, you can store the secret once and call the API whenever a 6-digit code is needed.

Secrets are encrypted at rest with AES-256-GCM. The plaintext secret is returned once at registration and never again.

Store a new TOTP secret. You can provide either a raw secret (base32) or a full otpauth:// URI from a QR code scan.

POST https://api.sendblue.com/api/v2/totp/secrets
ParameterTypeRequiredDescription
labelstringYes*Human-readable label (e.g. "GitHub - [email protected]"). Required unless uri is provided.
uristringNoFull otpauth://totp/... URI from a QR code. Overrides all other fields.
secretstringNoBase32-encoded TOTP secret. Omit to auto-generate.
issuerstringNoService name (e.g. "GitHub", "Google")
algorithmstringNoSHA1 (default), SHA256, or SHA512
digitsintegerNoCode length: 6 (default) or 8
periodintegerNoRotation period in seconds (default: 30)
Terminal window
curl -X POST 'https://api.sendblue.com/api/v2/totp/secrets' \
-H 'sb-api-key-id: YOUR_API_KEY' \
-H 'sb-api-secret-key: YOUR_API_SECRET' \
-H 'Content-Type: application/json' \
-d '{
"uri": "otpauth://totp/GitHub:agent%40example.com?secret=JBSWY3DPEHPK3PXP&issuer=GitHub"
}'
Terminal window
curl -X POST 'https://api.sendblue.com/api/v2/totp/secrets' \
-H 'sb-api-key-id: YOUR_API_KEY' \
-H 'sb-api-secret-key: YOUR_API_SECRET' \
-H 'Content-Type: application/json' \
-d '{
"label": "GitHub - [email protected]",
"secret": "JBSWY3DPEHPK3PXP",
"issuer": "GitHub"
}'

The plaintext secret is returned only on creation. Save it if you need it — it is never returned again.

{
"status": "OK",
"totp_secret": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"label": "GitHub - [email protected]",
"issuer": "GitHub",
"algorithm": "SHA1",
"digits": 6,
"period": 30,
"secret": "JBSWY3DPEHPK3PXP",
"created_at": "2026-04-05T12:00:00Z"
}
}

Generate the current code for a stored secret. Also returns expires_in — seconds until the code rotates — so your agent knows when to retry if a code is rejected.

GET https://api.sendblue.com/api/v2/totp/code/:secret_id
ParameterTypeDescription
secret_idstring (UUID)ID of the stored TOTP secret
Terminal window
curl 'https://api.sendblue.com/api/v2/totp/code/550e8400-e29b-41d4-a716-446655440000' \
-H 'sb-api-key-id: YOUR_API_KEY' \
-H 'sb-api-secret-key: YOUR_API_SECRET'
{
"status": "OK",
"code": "482031",
"expires_in": 14
}

expires_in is the number of seconds remaining in the current time window. If a 2FA form rejects the code, wait until expires_in reaches 0 and fetch a new one.


List all stored secrets for your account. Secret values are never included.

GET https://api.sendblue.com/api/v2/totp/secrets
Terminal window
curl 'https://api.sendblue.com/api/v2/totp/secrets' \
-H 'sb-api-key-id: YOUR_API_KEY' \
-H 'sb-api-secret-key: YOUR_API_SECRET'
{
"status": "OK",
"totp_secrets": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"label": "GitHub - [email protected]",
"issuer": "GitHub",
"algorithm": "SHA1",
"digits": 6,
"period": 30,
"created_at": "2026-04-05T12:00:00Z"
}
]
}

Permanently delete a stored secret.

DELETE https://api.sendblue.com/api/v2/totp/secrets/:secret_id
ParameterTypeDescription
secret_idstring (UUID)ID of the TOTP secret to delete
Terminal window
curl -X DELETE 'https://api.sendblue.com/api/v2/totp/secrets/550e8400-e29b-41d4-a716-446655440000' \
-H 'sb-api-key-id: YOUR_API_KEY' \
-H 'sb-api-secret-key: YOUR_API_SECRET'
{
"status": "OK"
}

{
"status": "ERROR",
"message": "label is required (or provide a uri)"
}
{
"status": "ERROR",
"message": "Unauthorized"
}
{
"status": "ERROR",
"message": "TOTP secret not found"
}
{
"status": "ERROR",
"message": "A secret with this label already exists"
}

  1. Security: Secrets are encrypted at rest with AES-256-GCM. The plaintext secret is only returned at registration time.
  2. URI format: Most services display a QR code during 2FA setup. If your setup flow shows a “can’t scan?” fallback, that link is the otpauth:// URI — pass it directly as uri.
  3. Timing: TOTP codes are time-based. If a code is rejected, check expires_in and wait for the next window before retrying.
  4. Label uniqueness: Labels must be unique within your account. Use descriptive labels like "service - [email protected]" to avoid conflicts.