API Documentation
Complete reference for all CognitoAPI endpoints, parameters, and responses
Authentication Requirements
The endpoints take no API key. Calls only send the inputs each endpoint documents, plus an Authorization: Bearer token where a signed-in user is required. Before exposing the API publicly, protect the unauthenticated endpoints at the edge (AWS WAF rate-limiting + API Gateway throttling) to guard against abuse and "financial DDoS" - an API key would not have stopped that anyway, since it is visible in every browser request.
Postman Collection Setup
You can find a Postman collection at postman/CognitoApi.postman_collection.json
You need to set the following variables inside Postman:
API_BASE_URL
The DNS name to use to call your auth API.
The email of the user you want to create.
PASSWORD
The password to use when you create a test user.
VerificationType
Must be set to SOFTWARE_TOKEN_MFA.
Note: The TOTP inside Postman is generated for you automatically using the MFA_SECRET environment variable, which is set from the API call output, once the user has been confirmed.
/v1/users
Create a new user in the Cognito User Pool
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| full_name | string | Required | User's full name |
string | Required | User's email | |
| mobile_phone_number | string | Required | User's mobile phone number |
Response
{
"email": "tarek@tocconsulting.fr",
"user_id": "129514d4-b081-7004-e470-b6adacd32db4",
"status": "CREATED"
}Example
import requests
import json
url = "https://your-api-id.execute-api.region.amazonaws.com/v1/users"
payload = {
"full_name": "Tarek CHEIKH",
"email": "tarek@tocconsulting.fr",
"mobile_phone_number": "+3301234567"
}
headers = {
"Content-Type": "application/json"
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
result = response.json()/v1/users/{user_id}/confirm
Confirm a new user with a temporary password and set a new password
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
string | Required | User's email | |
| temporary_password | string | Required | Temporary password sent to the user's email |
| new_password | string | Required | New password for the user |
Response
{
"email": "tarek@tocconsulting.fr",
"user_id": "129514d4-b081-7004-e470-b6adacd32db4",
"qr_code_secret": "UB42J65BKO473DIOOXGWOQZYT7AZKAS7W3AAHVTVT5IPRV",
"otpauth_uri": "otpauth://totp/CognitoApi:tarek@tocconsulting.fr?secret=UB42J65BKO473DIOOXGWOQZYT7AZKAS7W3AAHVTVT5IPRV&issuer=CognitoApi",
"mfa_session": "AYABeF...<session>",
"status": "PENDING_MFA"
}Example
import requests
import json
url = "https://your-api-id.execute-api.region.amazonaws.com/v1/users/{user_id}/confirm"
payload = {
"email": "tarek@tocconsulting.fr",
"temporary_password": "WpbyHbcIc#pNo3",
"new_password": "WpbyHbcIc#pNp9"
}
headers = {
"Content-Type": "application/json"
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
result = response.json()/v1/users/{user_id}/confirm-mfa
Confirm Multi-Factor Authentication for a user
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
string | Required | User's email | |
| otp | string | Required | One-time password from MFA device |
| mfa_session | string | Required | The MFA session returned by /confirm; required to complete enrollment |
Response
{
"email": "tarek@tocconsulting.fr",
"user_id": "129514d4-b081-7004-e470-b6adacd32db4",
"mfa_status": "CONFIRMED"
}Example
import requests
import json
url = "https://your-api-id.execute-api.region.amazonaws.com/v1/users/{user_id}/confirm-mfa"
payload = {
"email": "tarek@tocconsulting.fr",
"otp": "123456",
"mfa_session": "AYABeF...returned-by-/confirm..."
}
headers = {
"Content-Type": "application/json"
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
result = response.json()/v1/forgot-password
Initiate a password reset flow for a user
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
string | Required | User's email |
Response
{
"email": "tarek@tocconsulting.fr",
"user_id": "129514d4-b081-7004-e470-b6adacd32db4",
"status": "PASSWORD_FORGOT_CONFIRMATION_SENT"
}Example
import requests
import json
url = "https://your-api-id.execute-api.region.amazonaws.com/v1/forgot-password"
payload = {
"email": "tarek@tocconsulting.fr"
}
headers = {
"Content-Type": "application/json"
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
result = response.json()/v1/users/{user_id}/confirm-password
Complete password reset with verification code
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
string | Required | User's email | |
| new_password | string | Required | New password for the user |
| verification_code | string | Required | Verification code sent to the user |
Response
{
"email": "tarek@tocconsulting.fr",
"user_id": "129514d4-b081-7004-e470-b6adacd32db4",
"status": "NEW_PASSWORD_SET_SUCCESSFULLY"
}Example
import requests
import json
url = "https://your-api-id.execute-api.region.amazonaws.com/v1/users/{user_id}/confirm-password"
payload = {
"email": "tarek@tocconsulting.fr",
"new_password": "#Y3KdGR9QKg_a9",
"verification_code": "304482"
}
headers = {
"Content-Type": "application/json"
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
result = response.json()/v1/userinfo
Get information about the connected user
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| Authorization | header | Required | Bearer token from login |
Response
{
"name": "Tarek CHEIKH",
"user_id": "129514d4-b081-7004-e470-b6adacd32db4",
"email": "tarek@tocconsulting.fr",
"phone_number": "+3301234567",
"groups": []
}Example
import requests
url = "https://your-api-id.execute-api.region.amazonaws.com/v1/userinfo"
headers = {
"Authorization": "Bearer eyJraWQiOiJudUFPSENpcStPZnk3enF5TjFBZERSSEpQcUtZS1EwS"
}
response = requests.get(url, headers=headers)
result = response.json()/v1/resend-confirmation-code
Re-send the temporary password / confirmation code to an unconfirmed user.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
string | Required | User's email |
Response
{
"email": "tarek@tocconsulting.fr",
"user_id": "129514d4-b081-7004-e470-b6adacd32db4",
"status": "CONFIRMATION_CODE_SENT"
}Example
import requests, json
url = "https://your-api-id.execute-api.region.amazonaws.com/v1/resend-confirmation-code"
payload = { "email": "tarek@tocconsulting.fr" }
headers = { "Content-Type": "application/json" }
response = requests.post(url, headers=headers, data=json.dumps(payload))
result = response.json()/v1/users/{user_id}/change-password
Change the password of a signed-in user (requires the current password and a valid access token).
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
string | Required | User's email | |
| access_token | string | Required | The user's current access token |
| old_password | string | Required | The current password |
| new_password | string | Required | The new password (must meet the password policy) |
Response
{
"email": "tarek@tocconsulting.fr",
"status": "PASSWORD_SUCCESSFULLY_CHANGED"
}Example
import requests, json
url = "https://your-api-id.execute-api.region.amazonaws.com/v1/users/{user_id}/change-password"
payload = {
"email": "tarek@tocconsulting.fr",
"access_token": "eyJraWQiOi...",
"old_password": "OldPassw0rd#2026",
"new_password": "NewPassw0rd#2026"
}
headers = { "Content-Type": "application/json" }
response = requests.post(url, headers=headers, data=json.dumps(payload))
result = response.json()/v1/users/{user_id}/reset-password
Administratively force a password reset. Cognito emails a verification code the user completes via Confirm Forgot Password.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
string | Required | User's email |
Response
{
"email": "tarek@tocconsulting.fr",
"user_id": "129514d4-b081-7004-e470-b6adacd32db4",
"status": "PASSWORD_RESET_CONFIRMATION_SENT"
}Example
import requests, json
url = "https://your-api-id.execute-api.region.amazonaws.com/v1/users/{user_id}/reset-password"
payload = { "email": "tarek@tocconsulting.fr" }
headers = { "Content-Type": "application/json" }
response = requests.post(url, headers=headers, data=json.dumps(payload))
result = response.json()/v1/users/{user_id}
Permanently delete a user. Protected by the Cognito authorizer - requires the user's own ID token as a Bearer token. The target is the path {user_id}, which must match the token's subject; there is no request body.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| Authorization | header | Required | Bearer <id_token> (must belong to the {user_id} being deleted) |
Response
{
"email": "tarek@tocconsulting.fr",
"user_id": "129514d4-b081-7004-e470-b6adacd32db4",
"status": "USER_DELETED"
}Example
import requests
url = "https://your-api-id.execute-api.region.amazonaws.com/v1/users/{user_id}"
headers = {
"Authorization": "Bearer eyJraWQiOi..." # the user's own ID token
}
response = requests.delete(url, headers=headers)
result = response.json()/v1/login
First step of authentication to obtain verification session
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
string | Required | User's email | |
| password | string | Required | User's password |
Response
{
"email": "tarek@tocconsulting.fr",
"verification_session": "AYABeLHXhcXCnAA3E29UUMbVqKgAHQABAAdTZXJ2aWNlABBDb2duaXRvVXNlclBvb2xz",
"verification_type": "SOFTWARE_TOKEN_MFA"
}Example
import requests
import json
url = "https://your-api-id.execute-api.region.amazonaws.com/v1/login"
payload = {
"email": "tarek@tocconsulting.fr",
"password": "WpbyHbcIc#pNp9"
}
headers = {
"Content-Type": "application/json"
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
result = response.json()/v1/mfa-verify
Second step of authentication to complete MFA challenge
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
string | Required | User's email address | |
| verification_type | string | Required | Type of verification (SOFTWARE_TOKEN_MFA) |
| verification_session | string | Required | Session from login response |
| otp_code | string | Required | One-time password code from MFA device |
Response
{
"id_token": "eyJraWQiOiJpK0dwZFZLVUY1eG1ESml6Ukk2YTVWYTV6ZEtyXC8zeElyR",
"access_token": "eyJraWQiOiJudUFPSENpcStPZnk3enF5TjFBZERSSEpQcUtZS1EwS",
"refresh_token": "eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNB",
"expires_in": 3600
}Example
import requests
import json
url = "https://your-api-id.execute-api.region.amazonaws.com/v1/mfa-verify"
payload = {
"email": "tarek@tocconsulting.fr",
"verification_type": "SOFTWARE_TOKEN_MFA",
"verification_session": "AYABeLHXhcXCnAA3E29UUMbVqKgAHQABAAdTZXJ2aWNlABBDb2duaXRvVXNlclBvb2xz",
"otp_code": "012345"
}
headers = {
"Content-Type": "application/json"
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
result = response.json()/v1/refresh-token
Refresh expired tokens using a refresh token
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
string | Required | User's email | |
| refresh_token | string | Required | Valid refresh token from a previous login |
Response
{
"email": "tarek@tocconsulting.fr",
"id_token": "eyJraWQiOiJpK0dwZFZLVUY1eG1ESml6Ukk2YTVWYTV6ZEtyXC8zeElyR2owZk",
"access_token": "eyJraWQiOiJudUFPSENpcStPZnk3enF5TjFBZERSSEpQcUtZS1EwSU9mUGd",
"refresh_token": "eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVA",
"expires_in": 3600
}Example
import requests
import json
url = "https://your-api-id.execute-api.region.amazonaws.com/v1/refresh-token"
payload = {
"email": "tarek@tocconsulting.fr",
"refresh_token": "eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAifQ."
}
headers = {
"Content-Type": "application/json"
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
result = response.json()/v1/logout
Logout a user and invalidate tokens
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
string | Required | User's email | |
| access_token | string | Required | Access token to invalidate |
Response
{
"user_status": "logout"
}Example
import requests
import json
url = "https://your-api-id.execute-api.region.amazonaws.com/v1/logout"
payload = {
"email": "tarek@tocconsulting.fr",
"access_token": "eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoi"
}
headers = {
"Content-Type": "application/json"
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
result = response.json()/v1/mfa-reset/start
Begin authenticator recovery. Emails a one-time recovery code and returns a custom-auth session. Response is generic whether or not the account exists.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
string | Required | User's email |
Response
{
"status": "MFA_RESET_CODE_SENT",
"session": "AYABeF...<custom-auth-session>"
}Example
import requests, json
url = "https://your-api-id.execute-api.region.amazonaws.com/v1/mfa-reset/start"
payload = { "email": "tarek@tocconsulting.fr" }
headers = { "Content-Type": "application/json" }
response = requests.post(url, headers=headers, data=json.dumps(payload))
result = response.json()/v1/mfa-reset/verify
Verify the recovery code and password. Returns a fresh TOTP secret to enroll a new authenticator, plus an access token to confirm it.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
string | Required | User's email | |
| session | string | Required | Session returned by MFA Reset - Start |
| code | string | Required | Recovery code from the email |
| password | string | Required | The user's current password |
Response
{
"qr_code_secret": "MZXW6YTBOI======",
"otpauth_uri": "otpauth://totp/CognitoApi:tarek@tocconsulting.fr?secret=MZXW6YTBOI======&issuer=CognitoApi",
"access_token": "eyJraWQiOi...",
"status": "NEW_TOTP_ISSUED"
}Example
import requests, json
url = "https://your-api-id.execute-api.region.amazonaws.com/v1/mfa-reset/verify"
payload = {
"email": "tarek@tocconsulting.fr",
"session": "AYABeF...",
"code": "482913",
"password": "MyPassw0rd#2026"
}
headers = { "Content-Type": "application/json" }
response = requests.post(url, headers=headers, data=json.dumps(payload))
result = response.json()/v1/mfa-reset/confirm
Confirm the new authenticator with a 6-digit code, finishing the reset. The recovery session is then invalidated.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| access_token | string | Required | Access token from MFA Reset - Verify |
| otp | string | Required | 6-digit code from the new authenticator app |
Response
{
"status": "MFA_RESET_COMPLETE"
}Example
import requests, json
url = "https://your-api-id.execute-api.region.amazonaws.com/v1/mfa-reset/confirm"
payload = { "access_token": "eyJraWQiOi...", "otp": "123456" }
headers = { "Content-Type": "application/json" }
response = requests.post(url, headers=headers, data=json.dumps(payload))
result = response.json()/v1/passkeys/register/start
Begin registering a passkey for a signed-in user. Returns the WebAuthn credential creation options to pass to navigator.credentials.create().
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| access_token | string | Required | The signed-in user's access token |
Response
{
"credential_creation_options": {
"rp": { "id": "example.com", "name": "example.com" },
"user": { "id": "...", "name": "tarek@tocconsulting.fr", "displayName": "tarek@tocconsulting.fr" },
"challenge": "2Xs7JfjluJM16HAbVDZWrw",
"pubKeyCredParams": [{ "type": "public-key", "alg": -7 }, { "type": "public-key", "alg": -257 }],
"authenticatorSelection": { "residentKey": "required", "userVerification": "required" }
}
}Example
const start = await api("/v1/passkeys/register/start", { access_token });
const credential = await navigator.credentials.create({
publicKey: toBuffers(start.credential_creation_options),
});/v1/passkeys/register/complete
Finish passkey registration by sending the credential produced by the browser.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| access_token | string | Required | The signed-in user's access token |
| credential | object | Required | The PublicKeyCredential.toJSON() from navigator.credentials.create() |
Response
{
"status": "PASSKEY_REGISTERED"
}Example
await api("/v1/passkeys/register/complete", { access_token, credential: cred.toJSON() });/v1/passkeys/list
List the WebAuthn credentials registered for a signed-in user.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| access_token | string | Required | The signed-in user's access token |
Response
{
"credentials": [
{
"CredentialId": "x9s...",
"FriendlyCredentialName": "iCloud Keychain",
"RelyingPartyId": "example.com",
"AuthenticatorAttachment": "platform",
"CreatedAt": "2026-06-14T11:40:27Z"
}
]
}Example
const { credentials } = await api("/v1/passkeys/list", { access_token });/v1/passkeys/delete
Remove a registered passkey by its credential id.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| access_token | string | Required | The signed-in user's access token |
| credential_id | string | Required | Id of the credential to delete (from Passkey List) |
Response
{
"status": "PASSKEY_DELETED"
}Example
await api("/v1/passkeys/delete", { access_token, credential_id: "x9s..." });/v1/passkeys/login/start
Begin passwordless sign-in. Returns a session and the WebAuthn request options for navigator.credentials.get(). Response is generic whether or not the account/passkey exists.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
string | Required | User's email |
Response
{
"session": "AYABeF...",
"credential_request_options": "{\"challenge\":\"...\",\"rpId\":\"example.com\",\"allowCredentials\":[...]}"
}Example
const start = await api("/v1/passkeys/login/start", { email });
const assertion = await navigator.credentials.get({
publicKey: toBuffers(JSON.parse(start.credential_request_options)),
});/v1/passkeys/login/complete
Finish passwordless sign-in by answering the WebAuthn challenge. Returns tokens on success - no password or TOTP needed.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
string | Required | User's email | |
| session | string | Required | Session from Passkey Login - Start |
| credential | object | Required | The assertion from navigator.credentials.get() |
Response
{
"id_token": "eyJraWQiOi...",
"access_token": "eyJraWQiOi...",
"refresh_token": "eyJjdHkiOi...",
"expires_in": 3600,
"token_type": "Bearer"
}Example
const tokens = await api("/v1/passkeys/login/complete", {
email, session: start.session, credential: assertion.toJSON(),
});API Usage Notes
Authentication
The API takes no API key. Only GET /v1/userinfo and DELETE /v1/users/{id} require a Bearer JWT (enforced by a Cognito User Pools authorizer); the remaining endpoints are open. For protected calls, include the token in the Authorization header:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...Access tokens expire after a configurable period (typically 1 hour). Use the refresh token endpoint to obtain new tokens without requiring the user to log in again.
Error Handling
The API uses standard HTTP status codes along with detailed error information in the response body:
{
"message": "Invalid credentials"
}
{
"message": "Password does not meet complexity requirements"
}
{
"message": "Token has expired"
}Common Error Codes
- 400 Bad Request - The request could not be understood or was missing required parameters
- 401 Unauthorized - Authentication failed or user doesn't have permissions
- 403 Forbidden - Authenticated user doesn't have access to the requested resource
- 404 Not Found - Resource not found
- 429 Too Many Requests - Request throttled due to too many requests
- 500 Internal Server Error - An error occurred on the server
JWT Tokens
The API provides three types of tokens:
Token Types
- Access Token - Used to access protected resources, short-lived (typically 1 hour)
- ID Token - Contains user profile information, including email and other attributes
- Refresh Token - Used to obtain new access tokens when they expire, longer-lived (24 hours)
All tokens are JWT format, and you can decode them to inspect their contents using tools like jwt.io.
Deployment
The API is deployed using Terraform, making it easy to provision and manage your Cognito API infrastructure. The infrastructure is designed to be cost-efficient and secure.
AWS Resources
- API Gateway - REST API with CORS enabled
- Lambda Functions - Python-based handlers for authentication operations
- Cognito User Pool - User identity management
- CloudWatch Logs - Monitoring and troubleshooting
- IAM Roles and Policies - Secure access management
For details on deploying the API, refer to the Getting Started section and the project's README file on GitHub.