Authentication & User Management Authentication methods, user CRUD, getting started patterns

Base URL: https://api.fast.io/current/ Request format: application/x-www-form-urlencoded (POST) or query string (GET) Response format: JSON

Authentication Methods

All authenticated endpoints require: Authorization: Bearer {token}

The token can be a JWT (from Basic Auth or OAuth), an API key, or a 2FA-upgraded JWT.

Method 1: Basic Auth to JWT

Send HTTP Basic Auth (email:password) to get a JWT.

GET /current/user/auth/

Authorization: Basic {base64(email:password)}

Returns auth_token (JWT). If the account has 2FA enabled, the returned token has limited scope until 2FA verification is completed.

Method 2: API Keys

Long-lived tokens for service-to-service communication. Created via the API or the web UI. Used with the same Authorization: Bearer {api_key} header format as JWTs.

Method 3: OAuth 2.0 PKCE

For desktop/mobile apps and MCP-connected agents. No password passes through the agent. Access tokens last 1 hour, refresh tokens 30 days. S256 challenge method only. See the OAuth 2.0 reference for the full flow.

Method 4: 2FA

When 2FA is enabled on an account, Basic Auth returns a limited-scope JWT. Complete authentication via POST /current/user/auth/2factor/auth/{token}/ with the 2FA code. The response contains a full-scope JWT.

Getting Started

Option 1: Use a Human's Existing Account (API Key)

A human creates an API key and gives it to you. You operate as that user with their permissions, org, and billing.

Human instructions: "Go to Settings > Devices & Agents > API Keys and click Create API Key. Optionally enter a memo to label the key (e.g., 'Agent access'), then click Create. Copy the key immediately -- it is only displayed once. Direct link: https://go.fast.io/settings/api-keys"

Once you have the key: Authorization: Bearer {api_key}. No further steps needed.

Option 2: Create Your Own Agent Account (Autonomous)

Create your own account to work independently.

  1. POST /current/user/ with email_address, password, tos_agree=true, agent=true
  2. GET /current/user/auth/ with Basic Auth to get JWT
  3. Verify email:
    • POST /current/user/email/validate/ with email — sends verification code
    • POST /current/user/email/validate/ with email and email_token — validates the code
  4. POST /current/org/create/ with domain (required, 2-80 chars lowercase alphanumeric + hyphens)
  5. POST /current/org/{org_id}/create/workspace/ with folder_name, name, perm_join, perm_member_manage

Agent accounts get the agent plan: free, 50 GB storage, 5,000 credits/month, no expiration.

Option 3: Agent Account Invited to a Human's Org

  1. Create an agent account (steps 1-2 from Option 2)
  2. Give the human your agent's email address
  3. Human invites agent to their org or workspace
  4. Accept: POST /current/org/{org_id}/members/join/ or POST /current/workspace/{workspace_id}/members/join/
  5. You now operate within their resources with granted permissions

Option 4: PKCE Browser Login (No Password Sharing)

Most secure option. Works with SSO. No credentials pass through the agent.

  1. Agent initiates PKCE flow via POST /current/oauth/authorize/ with code_challenge, code_challenge_method=S256, client_id, redirect_uri, response_type=code
  2. User opens the returned URL in browser, signs in, approves access
  3. Browser displays authorization code — user copies it to agent
  4. Agent calls POST /current/oauth/token/ with grant_type=authorization_code, code, code_verifier
  5. Access tokens last 1 hour; refresh via POST /current/oauth/token/ with grant_type=refresh_token

Which option to choose

User Creation

POST /current/user/

Create a new user account.

Auth: None (IP-throttled)
Rate Limits: 5 per minute, 10 per hour, 20 per day (by IP)

Request Parameters

ParameterTypeRequiredConstraintsDescription
email_address string Yes Valid email format; domain must accept email; must be unique User's email address. Tags (e.g., +tag) are stripped for storage and uniqueness checks, but the original is preserved.
password string Yes Must pass password validity checks Account password.
tos_agree string Yes Must be "true" Must be "true" to accept Terms of Service.
agent string No "true" or "false" Set "true" for AI agent accounts. Sets account_type to "agent" permanently. Agent accounts skip email validation and use the agent plan.
first_name string No Must pass name validation User's given/first name.
last_name string No Must pass name validation User's family/last name.
phone_country string No Numeric country calling code Phone country code. Required if phone_number is provided.
phone_number string No Numeric phone number Phone number. Required if phone_country is provided.

Request Example

curl -X POST "https://api.fast.io/current/user/" \
  -d "email_address=jane.doe@example.com" \
  -d "password=SecureP@ss123" \
  -d "tos_agree=true" \
  -d "first_name=Jane" \
  -d "last_name=Doe" \
  -d "agent=true"

Success Response (200 OK)

{
  "result": "yes",
  "current_api_version": "1.0"
}

Response Fields

FieldTypeDescription
resultstring"yes" on success
current_api_versionstringAPI version ("1.0")

Error Responses

Error CodeHTTP StatusMessageCause
APP_ERROR_INPUT_INVALID (1605)400"An invalid email was supplied."Email format invalid
APP_ERROR_INPUT_INVALID (1605)400"The email domain is invalid or cannot receive email."Email domain validation failed
APP_ERROR_INPUT_INVALID (1605)400"The email supplied is already in use."Email already registered (after normalization)
APP_ERROR_INPUT_INVALID (1605)400"An invalid password was supplied."Password does not meet requirements
APP_ERROR_INPUT_INVALID (1605)400"An invalid tos_agree value was create."TOS value not a valid boolean string
APP_ERROR_INPUT_INVALID (1605)400"You declined to accept the terms of service."TOS set to "false"
APP_ERROR_INPUT_INVALID (1605)400"An invalid first name was supplied to create."First name fails validation
APP_ERROR_INPUT_INVALID (1605)400"An invalid last name was supplied to create."Last name fails validation
APP_ERROR_INPUT_INVALID (1605)400"An invalid phone country code was supplied."Invalid phone country code
APP_ERROR_INPUT_INVALID (1605)400"An invalid phone number was supplied."Invalid phone number
APP_ERROR_INPUT_INVALID (1605)400"An invalid phone number or country code was supplied."Full phone number validation failed
APP_DENIED (1680)403"Your attempt to create an account was not accepted."Risk/fraud check failed
APP_INTERNAL_ERROR (1600)500"We were unable to create your user account..."Internal commit failure

Notes

User Management Endpoints

POST /current/user/update/

Update the current authenticated user's profile information.

Auth: Required (JWT)
Rate Limits: 1 per 3s, 2 per 10s, 5 per minute, 20 per hour, 100 per day (by user)

Request Parameters

All fields are optional. Only provided fields are updated.

ParameterTypeRequiredConstraintsDescription
email_address string No Valid email format; unique; domain must accept email New email address. Resets email verification status.
password string No Must pass validity checks New password.
first_name string No Must pass name validation Updated given/first name.
last_name string No Must pass name validation Updated family/last name.
phone_country string No Numeric country code; 2FA must be disabled first Updated phone country code. Pass "null" or empty to clear.
phone_number string No Numeric phone number; 2FA must be disabled first Updated phone number. Pass "null" or empty to clear.
owner_defined string (JSON) No Must be valid JSON if provided Custom owner-defined properties. Pass null or empty to clear.

Request Example

curl -X POST "https://api.fast.io/current/user/update/" \
  -H "Authorization: Bearer {jwt_token}" \
  -d "first_name=Jane" \
  -d "last_name=Smith"

Success Response (200 OK)

{
  "result": "yes",
  "current_api_version": "1.0"
}

Error Responses

Error CodeHTTP StatusMessageCause
APP_ERROR_INPUT_INVALID (1605)400"An invalid email was supplied to update."Invalid email format
APP_ERROR_INPUT_INVALID (1605)400"The email domain is invalid or cannot receive email."Invalid email domain
APP_CONFLICT (1608)409"There email you specified is not available."Email already in use
APP_RESTRICTED (1681)403"You must disable 2-Factor before updating your phone."2FA enabled when trying to change phone
APP_ERROR_INPUT_INVALID (1605)400"An invalid password was supplied to update."Invalid password
APP_ERROR_INPUT_INVALID (1605)400"An invalid first name was supplied to update."Invalid first name
APP_ERROR_INPUT_INVALID (1605)400"An invalid last name was supplied to update."Invalid last name
APP_ERROR_INPUT_INVALID (1605)400"Owner-defined properties must be valid JSON."Invalid JSON in owner_defined

Notes


POST /current/user/close/

Close (soft-delete) the current user's account.

Auth: Required (JWT)

Request Parameters

ParameterTypeRequiredDescription
email_address string Yes Must match the user's current email address (confirmation).
dryrun string No If truthy, checks eligibility without closing the account.

Request Example

curl -X POST "https://api.fast.io/current/user/close/" \
  -H "Authorization: Bearer {jwt_token}" \
  -d "email_address=jane.doe@example.com"

Success Response (202 Accepted)

{
  "result": "yes",
  "current_api_version": "1.0"
}

Dry Run Response (Cannot Close, 202 Accepted)

{
  "result": "no",
  "current_api_version": "1.0"
}

Error Responses

Error CodeHTTP StatusMessageCause
APP_USER_NOT_FOUND (1653)404"User not found to close."User object invalid
APP_ERROR_INPUT_INVALID (1605)400"An invalid email was supplied to close account."Invalid email format
APP_ERROR_INPUT_INVALID (1605)400"An incorrect email was supplied to close account."Email does not match user's email
APP_ERROR_INPUT_INVALID (1605)400"Cannot close user account that owns active organizations..."User owns active organizations

Notes


POST /current/user/email/

Check if an email address is already in use.

Auth: None (IP-throttled)
Rate Limits: 50 per 30s, 500 per day (by IP)

Request Parameters

ParameterTypeRequiredDescription
email string Yes Email address to check availability.

Request Example

curl -X POST "https://api.fast.io/current/user/email/" \
  -d "email=jane.doe@example.com"

Email Available (202 Accepted)

{
  "result": "yes",
  "current_api_version": "1.0"
}

Email In Use (406 Not Acceptable)

{
  "result": "no",
  "current_api_version": "1.0"
}

Error Responses

Error CodeHTTP StatusMessageCause
APP_ERROR_INPUT_INVALID (1605)400"You provided an invalid email to check."Invalid email format or missing

Notes


POST /current/user/email/reset/

Request a password reset email.

Auth: None (IP-throttled)
Rate Limits: 2 per 2s, 10 per 10 minutes (by IP)

Request Parameters

ParameterTypeRequiredDescription
email string Yes Email address of the account.

Request Example

curl -X POST "https://api.fast.io/current/user/email/reset/" \
  -d "email=jane.doe@example.com"

Success Response (202 Accepted)

{
  "result": "yes",
  "current_api_version": "1.0"
}

Error Responses

Error CodeHTTP StatusMessageCause
APP_ERROR_INPUT_INVALID (1605)400"You provided an invalid email to check."Invalid email format
APP_INTERNAL_ERROR (1600)500"We were unable to send a verification email."Email send failure

Notes


POST /current/user/email/validate/

Send or validate an email verification code. Two-step flow.

Auth: Required (JWT)
Rate Limits: 1 per 3s, 2 per 10s, 5 per minute, 20 per hour, 100 per day (by user)

Mode 1: Send Verification Code

When email_token is NOT provided, sends a new validation code to the user's email.

ParameterTypeRequiredDescription
email string Yes Must match the authenticated user's email address.

Mode 2: Validate Code

When email_token IS provided, validates the code and marks the email as verified.

ParameterTypeRequiredDescription
email string Yes Must match the authenticated user's email address.
email_token string Yes Verification code received via email.

Request Example (Send Code)

curl -X POST "https://api.fast.io/current/user/email/validate/" \
  -H "Authorization: Bearer {jwt_token}" \
  -d "email=jane.doe@example.com"

Request Example (Validate Code)

curl -X POST "https://api.fast.io/current/user/email/validate/" \
  -H "Authorization: Bearer {jwt_token}" \
  -d "email=jane.doe@example.com" \
  -d "email_token=123456"

Success Response (202 Accepted)

{
  "result": "yes",
  "current_api_version": "1.0"
}

Error Responses

Error CodeHTTP StatusMessageCause
APP_AUTH_INVALID (1650)401"Your credentials were not supplied or invalid."User not authenticated
APP_NOT_ACCEPTABLE (1606)406"Your email address is already verified."Email already verified
APP_CONFLICT (1608)409"Your credentials do not match the email you provided."Email mismatch with authenticated user
APP_NOT_ACCEPTABLE (1606)406"You provided an invalid or expired token to validate email."Invalid or expired code
APP_DENIED (1680)403"Provided code has expired, get a new code and try again."Code expired

POST /current/user/password/{code}/

Set a new password using a password reset code.

Auth: None (code-based authentication)

Path Parameters

ParameterTypeRequiredDescription
{code} string Yes Password reset code from the reset email.

Request Parameters

ParameterTypeRequiredDescription
password1 string Yes New password.
password2 string Yes New password confirmation. Must match password1.

Request Example

curl -X POST "https://api.fast.io/current/user/password/abc123def456/" \
  -d "password1=NewSecureP@ss" \
  -d "password2=NewSecureP@ss"

Success Response (202 Accepted)

{
  "result": "yes",
  "current_api_version": "1.0"
}

Error Responses

Error CodeHTTP StatusMessageCause
APP_DENIED (1680)403"An invalid code was provided, cannot reset password."Invalid code format
APP_DENIED (1680)403"Provided code was not found or expired, cannot reset password."Code not found or wrong type
APP_DENIED (1680)403"Provided code has expired, get a new code and try again."Code expired
APP_CONFLICT (1608)409"Provided code belongs to another user account and cannot be used."Code/user mismatch
APP_MISSING (1609)404"The provided code belongs to an invalid user."User not found for code
APP_CONFLICT (1608)409"The provided passwords don't match."password1 and password2 differ
APP_NOT_ACCEPTABLE (1606)406"Both password fields must be provided and match."Missing password fields
APP_INTERNAL_ERROR (1600)500"The provided password could not be processed..."Encryption failure

Notes


GET /current/user/password/{code}/details/

Get details of a password reset code (check if valid/expired).

Auth: None (code-based)

Path Parameters

ParameterTypeRequiredDescription
{code} string Yes Password reset code to check.

Request Example

curl -X GET "https://api.fast.io/current/user/password/abc123def456/details/"

Success Response (200 OK)

{
  "result": "yes",
  "response": {
    "email": "jane.doe@example.com"
  },
  "current_api_version": "1.0"
}

Response Fields

FieldTypeDescription
response.emailstringThe email address associated with the reset code.

Error Responses

Error CodeHTTP StatusMessageCause
APP_DENIED (1680)403"An invalid code was provided, cannot reset password."Invalid code format
APP_DENIED (1680)403"Provided code was not found or expired, cannot reset password."Code not found
APP_DENIED (1680)403"Provided code has expired, get a new code and try again."Code expired
APP_CONFLICT (1608)409"Provided code belongs to another user account..."Code/user mismatch
APP_LOCKED (1682)423"The account has been restricted and cannot be updated."Account locked/suspended/closed

GET /current/user/phone/{country_code}-{phone_number}/

Validate a phone number and country code combination.

Auth: Required (JWT)

Path Parameters

ParameterTypeRequiredDescription
{country_code}-{phone_number} string Yes Country code and phone number separated by a hyphen (e.g., 1-5551234567).

Request Example

curl -X GET "https://api.fast.io/current/user/phone/1-5551234567/" \
  -H "Authorization: Bearer {jwt_token}"

Success Response (202 Accepted)

{
  "result": "yes",
  "current_api_version": "1.0"
}

Error Responses

Error CodeHTTP StatusMessageCause
APP_ERROR_INPUT_INVALID (1605)400"You provided an invalid phone number to check."Invalid format
APP_ERROR_INPUT_INVALID (1605)400"An invalid phone country code was supplied."Invalid country code
APP_ERROR_INPUT_INVALID (1605)400"An invalid phone number was supplied."Invalid phone number
APP_ERROR_INPUT_INVALID (1605)400"An invalid phone number or country code was supplied."Full number validation failed

GET /current/user/pin/

Get the user's support PIN and identity verification hash.

Auth: Required (JWT)

Request Example

curl -X GET "https://api.fast.io/current/user/pin/" \
  -H "Authorization: Bearer {jwt_token}"

Success Response (200 OK)

{
  "result": "yes",
  "response": {
    "supportcode": "1234",
    "intercom": "a1b2c3d4e5f6..."
  },
  "current_api_version": "1.0"
}

Response Fields

FieldTypeDescription
response.supportcodestring4-digit support PIN. Defaults to "0000" if not set.
response.intercomstringHMAC-SHA256 identity verification hash.

Error Responses

Error CodeHTTP StatusMessageCause
APP_USER_NOT_FOUND (1653)404"Unable to fetch the user details."User not found
APP_INTERNAL_ERROR (1600)500"Internal temporary error, please try again later."Failed to load credentials

GET|POST /current/user/sso/signin/{provider}/

SSO (Single Sign-On) authentication flow.

Auth: None (IP-throttled)
Rate Limits: 30 per 5s, 60 per 30s, 600 per 5 minutes (by IP)

Path Parameters

ParameterTypeRequiredDescription
{provider} string Yes SSO provider name: google, apple, or microsoft.

GET: Get SSO Redirect URL

Returns the OAuth2 authorization URL for the specified provider.

curl -X GET "https://api.fast.io/current/user/sso/signin/google/"

GET Response (200 OK)

{
  "result": "yes",
  "response": {
    "provider": "google",
    "redirect_url": "https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=...",
    "return_url": "https://fast.io/sso/callback/google"
  },
  "current_api_version": "1.0"
}

Response Fields

FieldTypeDescription
response.providerstringThe provider name.
response.redirect_urlstringURL to redirect the user to for SSO authentication.
response.return_urlstringCallback URL the provider will redirect back to.

POST: Process SSO Callback

Processes the OAuth2 callback with the authorization code from the provider.

ParameterTypeRequiredDescription
code string Yes Authorization code from the SSO provider.
state string Yes State token for CSRF protection.

Error Responses

Error CodeHTTP StatusMessageCause
APP_ERROR_INPUT_INVALID (1605)400"An invalid provider name was supplied."Invalid provider name format
APP_ERROR_INPUT_INVALID (1605)400"An unknown provider name was supplied."Provider not in allowed list
APP_ERROR_INPUT_INVALID (1605)400"Cookies must be enabled and passed to this API."Missing state cookie
APP_DENIED (1680)403"Permission was not granted by the provider."OAuth error returned from provider
APP_SSO_ERROR_AUTH (1690)401"Invalid or missing input in a required field was received."Missing code or state

Notes


GET /current/user/assets/

List available user asset metadata types (e.g., profile photo specifications).

Auth: None

Request Example

curl -X GET "https://api.fast.io/current/user/assets/"

Notes


GET /current/user/available_profiles/

Check what profile types (orgs, workspaces, shares) the current user has access to.

Auth: Required (JWT)

Request Example

curl -X GET "https://api.fast.io/current/user/available_profiles/" \
  -H "Authorization: Bearer {jwt_token}"

Success Response (200 OK)

{
  "result": "yes",
  "response": {
    "has_orgs": true,
    "has_workspaces": true,
    "has_shares": false
  },
  "current_api_version": "1.0"
}

Response Fields

FieldTypeDescription
response.has_orgsbooleanWhether the user has access to any organizations.
response.has_workspacesbooleanWhether the user has access to any workspaces.
response.has_sharesbooleanWhether the user has access to any shares.

Error Responses

Error CodeHTTP StatusMessageCause
APP_USER_NOT_FOUND (1653)404"Unable to fetch the user details."User not found

GET /current/user/{user_id}/details/

Get user profile details.

Auth: Required (JWT)

Path Parameters

ParameterTypeRequiredDescription
{user_id} string No 20-digit user ID. If omitted, returns the current user's details.

Request Example

curl -X GET "https://api.fast.io/current/user/1234567890123456789/details/" \
  -H "Authorization: Bearer {jwt_token}"

Success Response (200 OK)

{
  "result": "yes",
  "response": {
    "user": {
      "id": "12345678901234567890",
      "account_type": "human",
      "email_address": "jane.doe@example.com",
      "first_name": "Jane",
      "last_name": "Doe",
      "locked": false,
      "profile_pic": "https://assets.fast.io/..."
    }
  },
  "current_api_version": "1.0"
}

Response Fields

FieldTypeDescription
response.user.idstring20-digit user ID.
response.user.account_typestring"human" or "agent".
response.user.email_addressstringUser's email address.
response.user.first_namestringGiven name.
response.user.last_namestringFamily name.
response.user.lockedbooleanWhether the account is locked.
response.user.profile_picstringProfile photo URL.

Self-Only Fields (included only when viewing your own profile)

FieldTypeDescription
2factorbooleanWhether 2FA is enabled.
closedbooleanWhether the account is closed.
country_codestringCountry of residence.
createdstringRegistration date.
phone_countrystringPhone country code.
phone_numberstringPhone number.
suspendedbooleanSuspension status.
tos_agreestringToS agreement date.
updatedstringLast profile update time.
valid_emailbooleanEmail verified status.
valid_phonebooleanPhone verified status.

Error Responses

Error CodeHTTP StatusMessageCause
APP_USER_NOT_FOUND (1653)404"Unable to fetch the user details."User not found

GET /current/user/me/autosync/{state}/

Enable or disable profile photo auto-synchronization from SSO providers.

Auth: Required (JWT)

Path Parameters

ParameterTypeRequiredDescription
{state} string Yes "enable" or "disable".

Request Example

curl -X GET "https://api.fast.io/current/user/me/autosync/enable/" \
  -H "Authorization: Bearer {jwt_token}"

Success Response (200 OK)

{
  "result": "yes",
  "current_api_version": "1.0"
}

Error Responses

Error CodeHTTP StatusMessageCause
APP_ERROR_DATASTORE (1600)500"There was an internal error processing your request..."Commit failure

GET /current/user/me/allowed/

Check if the user's country (based on IP geolocation) allows creating shares or organizations.

Auth: None (IP-throttled)
Rate Limits: 100 per minute, 1000 per day (by IP)

Request Example

curl -X GET "https://api.fast.io/current/user/me/allowed/"

Success Response (200 OK)

{
  "result": "yes",
  "response": {
    "allowed": true
  },
  "current_api_version": "1.0"
}

Response Fields

FieldTypeDescription
response.allowedbooleanWhether the user's location allows resource creation.
response.reasonsarrayArray of blocked reason strings. Only present when allowed is false.

GET /current/user/me/limits/orgs/

Check free organization creation eligibility.

Auth: Required (JWT)
Rate Limits: 60 per minute, 1000 per day (by IP and user)

Request Example

curl -X GET "https://api.fast.io/current/user/me/limits/orgs/" \
  -H "Authorization: Bearer {jwt_token}"

Success Response (200 OK)

{
  "result": "yes",
  "response": {
    "can_create_free_org": true,
    "existing_free_orgs": 0,
    "cooldown_remaining": 0,
    "max_free_orgs": 1
  },
  "current_api_version": "1.0"
}

Response Fields

FieldTypeDescription
response.can_create_free_orgbooleanWhether the user can create a free organization.
response.existing_free_orgsintegerNumber of existing free organizations owned by the user.
response.cooldown_remainingintegerSeconds remaining before next creation is allowed.
response.max_free_orgsintegerMaximum number of free organizations allowed.
response.reasonstringReason creation is not allowed. Only present when can_create_free_org is false.

Error Responses

Error CodeHTTP StatusMessageCause
APP_USER_NOT_FOUND (1653)404"Unable to fetch the user."User not found

GET /current/user/me/list/shares/

List all shares accessible to the current user.

Auth: Required (JWT)
Rate Limits: 100 per minute, 1500 per hour, 5000 per day (by user)

Query Parameters

ParameterTypeRequiredDefaultDescription
archived string No "false" "true" to show archived shares, "false" to show non-archived.

Request Example

curl -X GET "https://api.fast.io/current/user/me/list/shares/" \
  -H "Authorization: Bearer {jwt_token}"

Success Response (200 OK)

{
  "result": "yes",
  "response": {
    "shares": [
      {
        "id": "12345678901234567890",
        "name": "Project Files",
        "type": "send",
        "archived": false
      }
    ]
  },
  "current_api_version": "1.0"
}

Response Fields

FieldTypeDescription
response.sharesarrayArray of share resource objects. Each includes parent workspace and org info.

Notes


GET /current/user/{user_id}/assets/

List set assets (e.g., profile photo) for a user.

Auth: Required (JWT)

Path Parameters

ParameterTypeRequiredDescription
{user_id} string Yes 20-digit numeric user ID.

Request Example

curl -X GET "https://api.fast.io/current/user/12345678901234567890/assets/" \
  -H "Authorization: Bearer {jwt_token}"

POST|DELETE /current/user/{user_id}/assets/{asset_name}/

Upload or delete a user asset.

Auth: Required (JWT)

Path Parameters

ParameterTypeRequiredDescription
{user_id} string Yes 20-digit numeric user ID.
{asset_name} string Yes Asset type name (e.g., profile_pic).

POST: Upload Asset

Multipart form data with exactly one file upload.

ParameterTypeRequiredDescription
(file) file Yes The asset file. Exactly one file must be included.
metadata array No Optional metadata. Must be a valid array if provided.

DELETE: Delete Asset

No request body required.

Error Responses

Error CodeHTTP StatusMessageCause
APP_REQUEST_TYPE (1651)400"Only user may modify."Non-owner attempting to modify
APP_POST_FILE_MISSING (1604)400"Asset upload missing"No file in POST request
APP_ERROR_INPUT_INVALID (1605)400"metadata invalid"Invalid metadata parameter

Notes


GET|HEAD /current/user/{user_id}/assets/{asset_name}/read/

Read the binary content of a user asset.

Auth: Required (JWT)

Path Parameters

ParameterTypeRequiredDescription
{user_id} string Yes 20-digit numeric user ID.
{asset_name} string Yes Asset type name (e.g., profile_pic).

Notes

Invitations

GET /current/user/invitation/{invitation_id}/details/

Get details for a specific invitation.

Auth: Required (JWT)
Rate Limits: 10 per minute, 20 per 10 minutes, 30 per hour (by user)

Path Parameters

ParameterTypeRequiredDescription
{invitation_id} string Yes Invitation ID (numeric) or invitation key (alphanumeric).

Request Example

curl -X GET "https://api.fast.io/current/user/invitation/12345678901234567890/details/" \
  -H "Authorization: Bearer {jwt_token}"

Success Response (200 OK)

{
  "result": "yes",
  "response": {
    "invitation": {
      "id": "12345678901234567890",
      "entity": "98765432101234567890",
      "state": "pending",
      "email": "jane.doe@example.com"
    },
    "owner": {
      "id": "11111111111111111111",
      "account_type": "human",
      "email_address": "admin@example.com",
      "first_name": "Admin",
      "last_name": "User",
      "profile_pic": "https://assets.fast.io/..."
    },
    "org": {
      "id": "22222222222222222222",
      "name": "Example Org"
    }
  },
  "current_api_version": "1.0"
}

Response Fields

FieldTypeDescription
response.invitationobjectInvitation resource.
response.ownerobjectUser resource of the profile owner.
response.orgobject or nullOrg resource if the invitation is for an org-owned entity.

Error Responses

Error CodeHTTP StatusMessageCause
APP_ERROR_INPUT_INVALID (1605)400"An invalid invitation ID was supplied."Invalid ID format
APP_ERROR_INPUT_INVALID (1605)400"Invitation not found."Invitation does not exist
APP_INTERNAL_ERROR (1600)500"Failed to load the invitation profile or its owner."Profile or owner load failure

GET /current/user/invitation/{invitation_id}/public/details/

Get public details for an invitation without authentication.

Auth: None (IP-throttled)
Rate Limits: 15 per 10s, 100 per hour, 500 per day (by IP)

Path Parameters

ParameterTypeRequiredDescription
{invitation_id} string Yes Invitation ID (numeric) or invitation key (alphanumeric).

Request Example

curl -X GET "https://api.fast.io/current/user/invitation/12345678901234567890/public/details/"

Success Response (200 OK)

{
  "result": "yes",
  "response": {
    "invitation": {
      "id": "12345678901234567890",
      "state": "pending"
    },
    "owner": {
      "id": "11111111111111111111",
      "account_type": "human",
      "first_name": "Admin",
      "last_name": "User"
    },
    "org": {
      "id": "22222222222222222222",
      "name": "Example Org"
    }
  },
  "current_api_version": "1.0"
}

Notes


POST /current/user/invitations/acceptall/

Accept all pending invitations.

Auth: Required (JWT)
Rate Limits: 10 per minute, 20 per 10 minutes, 30 per hour (by user)

Request Parameters

ParameterTypeRequiredDescription
invitation_key string No Optional invitation key. If the user's email is not validated, this key can identify invitations.

Request Example

curl -X POST "https://api.fast.io/current/user/invitations/acceptall/" \
  -H "Authorization: Bearer {jwt_token}"

Success Response (200 OK)

{
  "result": "yes",
  "current_api_version": "1.0"
}

Notes


GET /current/user/invitations/list/

List all pending invitations for the current user.

Auth: Required (JWT)
Rate Limits: 10 per minute, 20 per 10 minutes, 30 per hour (by user)

Query Parameters

ParameterTypeRequiredDescription
invitation_key string No Optional invitation key for users without validated email.

Request Example

curl -X GET "https://api.fast.io/current/user/invitations/list/" \
  -H "Authorization: Bearer {jwt_token}"

Success Response (200 OK)

{
  "result": "yes",
  "response": {
    "invitations": [
      {
        "id": "12345678901234567890",
        "entity": "98765432101234567890",
        "state": "pending",
        "email": "jane.doe@example.com"
      }
    ]
  },
  "current_api_version": "1.0"
}

Response Fields

FieldTypeDescription
response.invitationsarrayArray of invitation resource objects.

User Authentication Endpoints

GET /current/user/auth/

Authenticate via HTTP Basic Auth. Returns JWT token.

Auth: HTTP Basic Auth (email:password)
Rate Limits: 60 per hour, 240 per day (by IP)

Query Parameters

ParameterTypeRequiredDefaultDescription
expires integer No Server default Custom JWT expiration time in seconds.

Request Example

curl -X GET "https://api.fast.io/current/user/auth/" \
  -u "jane.doe@example.com:SecureP@ss123"

Success Response (200 OK)

{
  "result": "yes",
  "response": {
    "expires_in": 86400,
    "auth_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
    "2factor": false
  },
  "current_api_version": "1.0"
}

Response Fields

FieldTypeDescription
response.expires_inintegerJWT token expiration time in seconds.
response.auth_tokenstringJWT access token. If 2FA is enabled, has twofactor scope (restricted). Otherwise has user scope (full access).
response.2factorbooleantrue if 2FA is enabled. Token has limited scope until 2FA verification is completed.

Error Responses

Error CodeHTTP StatusMessageCause
APP_REQUEST_TYPE (1651)400"The expires time specified is invalid."Invalid expires parameter
APP_AUTH_INVALID (1650)401"Your credentials were not supplied or invalid."Missing Basic Auth header
APP_AUTH_INVALID (1650)401"Username is not valid."Invalid email format
APP_AUTH_INVALID (1650)401"Password is not valid."Invalid password format
APP_USER_NOT_FOUND (1653)404"The username was not found."Email not registered
APP_AUTH_INVALID (1650)401"The password on this account is not set, use SSO."SSO-only account (no password set)
APP_AUTH_INVALID (1650)401"Your credentials supplied are invalid."Wrong password
APP_AUTH_INVALID (1650)401"Your account is suspended..."Account suspended
APP_AUTH_INVALID (1650)401"Your account is locked..."Account locked
APP_AUTH_INVALID (1650)401"Your account is suspended due to abuse."Account flagged for abuse
APP_AUTH_INVALID (1650)401"Your account is closed by you."Account closed

Notes


GET /current/user/auth/check/

Validate current JWT and get user ID.

Auth: Required (Bearer token)
Rate Limits: 20 per 3s, 50 per 10s, 100 per minute, 5000 per hour, 20000 per day (by IP)

Request Example

curl -X GET "https://api.fast.io/current/user/auth/check/" \
  -H "Authorization: Bearer {jwt_token}"

Success Response (200 OK)

{
  "result": "yes",
  "response": {
    "id": "12345678901234567890"
  },
  "current_api_version": "1.0"
}

Response Fields

FieldTypeDescription
response.idstringThe 20-digit numeric user ID.

Notes


GET /current/auth/scopes/

Token scope introspection. Returns information about the current token's scope, auth type, and agent status.

Auth: Required (Bearer token)
Rate Limits: 60 per minute, 600 per hour (by user and IP)

Request Example

curl -X GET "https://api.fast.io/current/auth/scopes/" \
  -H "Authorization: Bearer {jwt_token}"

Success Response (200 OK)

{
  "result": "yes",
  "response": {
    "auth_type": "jwt_v2",
    "scopes": ["org:12345:rw", "org:67890:rw"],
    "scopes_detail": [],
    "is_agent": true,
    "agent_name": "My MCP Agent",
    "full_access": false
  },
  "current_api_version": "1.0"
}

Response Fields

FieldTypeDescription
response.auth_typestringToken type: "jwt_v2" (scoped JWT), "jwt_v1" (legacy JWT), or "api_key".
response.scopesarrayArray of scope strings in entity_type:entity_id:access_mode format. Empty for v1 JWTs and API keys.
response.scopes_detailarrayHydrated scope details with entity information. Empty when scopes are empty.
response.is_agentbooleanWhether the token represents an agent.
response.agent_namestring or nullAgent display name. null if not set or not an agent.
response.full_accessbooleanWhether the token has unrestricted access. true for v1 JWTs and API keys.

API Keys

POST /current/user/auth/key/

Create a new API key.

Auth: Required (JWT, scope: user or admin)

Request Parameters

ParameterTypeRequiredDescription
memo string No Label/description for the key.

Request Example

curl -X POST "https://api.fast.io/current/user/auth/key/" \
  -H "Authorization: Bearer {jwt_token}" \
  -d "memo=CI/CD Pipeline Key"

Success Response (200 OK)

{
  "result": "yes",
  "response": {
    "api_key": "abcdefghij1234567890abcdefghij12"
  },
  "current_api_version": "1.0"
}

Response Fields

FieldTypeDescription
response.api_keystringThe newly created API key. Only shown once — store it securely.

Error Responses

Error CodeHTTP StatusMessageCause
APP_AUTH_INVALID (1650)401"Your credentials were not supplied or invalid."Missing or invalid JWT
APP_AUTH_INVALID (1650)401"The scope of your credentials are not sufficient."JWT scope not user or admin
APP_INTERNAL_ERROR (1600)500"You are at the maximum number of API keys, {max}."Maximum key limit reached
APP_ERROR_INPUT_INVALID (1605)400"You provided an invalid Memo."Invalid memo format

Notes


GET /current/user/auth/key/{key_id}/

Get details of an API key (key value is masked).

Auth: Required (JWT, scope: user or admin)

Path Parameters

ParameterTypeRequiredDescription
{key_id} string Yes The API key's unique identifier.

Request Example

curl -X GET "https://api.fast.io/current/user/auth/key/key_12345/" \
  -H "Authorization: Bearer {jwt_token}"

Success Response (200 OK)

{
  "result": "yes",
  "response": {
    "api_key": {
      "id": "key_12345",
      "api_key": "****************************ab12",
      "memo": "CI/CD Pipeline Key",
      "created": "2024-01-15 10:30:00 UTC"
    }
  },
  "current_api_version": "1.0"
}

Response Fields

FieldTypeDescription
response.api_key.idstringUnique key identifier.
response.api_key.api_keystringMasked API key (only last 4 characters visible).
response.api_key.memostringKey description/label.
response.api_key.createdstringKey creation timestamp in UTC.

Error Responses

Error CodeHTTP StatusMessageCause
APP_ERROR_INPUT_INVALID (1605)400"You provided an invalid Token to get details of."Invalid key ID format
APP_ERROR_NOT_FOUND (1609)404Key not foundKey does not exist

DELETE /current/user/auth/key/{key_id}/

Delete an API key.

Auth: Required (JWT, scope: user or admin)

Path Parameters

ParameterTypeRequiredDescription
{key_id} string Yes The API key's unique identifier.

Request Example

curl -X DELETE "https://api.fast.io/current/user/auth/key/key_12345/" \
  -H "Authorization: Bearer {jwt_token}"

Success Response (200 OK)

{
  "result": "yes",
  "current_api_version": "1.0"
}

Error Responses

Error CodeHTTP StatusMessageCause
APP_ERROR_INPUT_INVALID (1605)400"You provided an invalid Token to Delete."Invalid key ID format
APP_ERROR_NOT_FOUND (1609)404"You provided a Token that was not found."Key not found or belongs to another user
APP_ERROR_DELETE_ERROR (1610)500"There was an error deleting the API Key."Internal deletion failure

Notes


GET /current/user/auth/keys/

List all API keys for the user.

Auth: Required (JWT)

Request Example

curl -X GET "https://api.fast.io/current/user/auth/keys/" \
  -H "Authorization: Bearer {jwt_token}"

Success Response (200 OK)

{
  "result": "yes",
  "response": {
    "results": 2,
    "api_keys": [
      {
        "id": "key_12345",
        "api_key": "****************************ab12",
        "memo": "CI/CD Pipeline Key",
        "created": "2024-01-15 10:30:00 UTC"
      },
      {
        "id": "key_67890",
        "api_key": "****************************cd34",
        "memo": "Backup Script",
        "created": "2024-02-20 14:00:00 UTC"
      }
    ]
  },
  "current_api_version": "1.0"
}

No Keys Response (200 OK)

{
  "result": "yes",
  "response": {
    "results": 0,
    "api_keys": null
  },
  "current_api_version": "1.0"
}

Response Fields

FieldTypeDescription
response.resultsintegerNumber of API keys.
response.api_keysarray or nullArray of API key objects, or null if none exist.
response.api_keys[].idstringUnique key identifier.
response.api_keys[].api_keystringMasked API key (only last 4 characters visible).
response.api_keys[].memostringKey description/label.
response.api_keys[].createdstringKey creation timestamp in UTC.

Two-Factor Authentication (2FA)

GET /current/user/auth/2factor/

Get current 2FA status.

Auth: Required (JWT, scope: user or admin)

Request Example

curl -X GET "https://api.fast.io/current/user/auth/2factor/" \
  -H "Authorization: Bearer {jwt_token}"

Success Response (200 OK)

{
  "result": "yes",
  "response": {
    "state": "enabled",
    "totp": false
  },
  "current_api_version": "1.0"
}

Response Fields

FieldTypeDescription
response.statestring2FA status: "enabled" (fully verified), "unverified" (added but not verified), or "disabled" (not configured).
response.totpbooleanWhether the 2FA method is TOTP (Time-based One-Time Password).

POST /current/user/auth/2factor/{channel}/

Enable 2FA on the account.

Auth: Required (JWT, scope: user or admin)

Path Parameters

ParameterTypeRequiredDefaultDescription
{channel} string No sms 2FA delivery channel: sms, call, whatsapp, or totp.

Request Example

curl -X POST "https://api.fast.io/current/user/auth/2factor/sms/" \
  -H "Authorization: Bearer {jwt_token}"

Success Response for SMS/Voice/WhatsApp (202 Accepted)

{
  "result": "yes",
  "current_api_version": "1.0"
}

Success Response for TOTP (202 Accepted)

{
  "result": "yes",
  "response": {
    "binding_uri": "otpauth://totp/fast.io:jane@example.com?secret=ABCDEF..."
  },
  "current_api_version": "1.0"
}

Response Fields (TOTP only)

FieldTypeDescription
response.binding_uristringTOTP provisioning URI for QR code display.

Error Responses

Error CodeHTTP StatusMessageCause
APP_EXISTS (1607)409"2Factor already added, please remove first."2FA already enabled
APP_ERROR_INPUT_INVALID (1605)400"An invalid channel was supplied."Invalid channel name
APP_NOT_ACCEPTED (1606)406"2Factor cannot be added, you need a valid phone_number and phone_country..."No phone number configured

Notes


POST /current/user/auth/2factor/verify/{token}/

Verify a 2FA setup code to confirm enrollment. Transitions 2FA from unverified to enabled state.

Auth: Required (JWT)

Path Parameters

ParameterTypeRequiredDescription
{token} string Yes 2FA verification code (e.g., 6-digit code).

Request Example

curl -X POST "https://api.fast.io/current/user/auth/2factor/verify/123456/" \
  -H "Authorization: Bearer {jwt_token}"

Success Response (202 Accepted)

{
  "result": "yes",
  "current_api_version": "1.0"
}

Verification Failed (406 Not Accepted)

{
  "result": "no",
  "current_api_version": "1.0"
}

Error Responses

Error CodeHTTP StatusMessageCause
APP_ERROR_INPUT_INVALID (1605)400"An invalid token was supplied to validate."Invalid token format
APP_NOT_ACCEPTABLE (1606)406"2Factor is not enabled."2FA not configured

Notes


POST /current/user/auth/2factor/auth/{token}/

Authenticate with a 2FA code. Upgrades a limited-scope JWT to a full-scope JWT.

Auth: Required (JWT, scope: user, twofactor, or admin)

Path Parameters

ParameterTypeRequiredDescription
{token} string Yes Valid 2FA verification code (e.g., 6-digit TOTP or SMS code).

Request Example

curl -X POST "https://api.fast.io/current/user/auth/2factor/auth/123456/" \
  -H "Authorization: Bearer {twofactor_jwt_token}"

Success Response (200 OK)

{
  "result": "yes",
  "response": {
    "expires_in": 86400,
    "auth_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
  },
  "current_api_version": "1.0"
}

Response Fields

FieldTypeDescription
response.expires_inintegerJWT expiration time in seconds.
response.auth_tokenstringNew JWT with full user scope.

Error Responses

Error CodeHTTP StatusMessageCause
APP_ERROR_INPUT_INVALID (1605)400"An invalid token was supplied to authenticate."Invalid token format
APP_NOT_ACCEPTED (1606)406"2Factor is not enabled on this account."2FA not enabled
APP_NOT_ACCEPTED (1606)406"The supplied token failed to authenticate."Wrong 2FA code
APP_AUTH_INVALID (1650)401"Internal Error."JWT creation failure

DELETE /current/user/auth/2factor/{token}/

Disable (remove) 2FA from the account.

Auth: Required (JWT, scope: user or admin)

Path Parameters

ParameterTypeRequiredDescription
{token} string Yes Valid 2FA verification code. Required only if 2FA is in enabled (verified) state.

Request Example

curl -X DELETE "https://api.fast.io/current/user/auth/2factor/123456/" \
  -H "Authorization: Bearer {jwt_token}"

Success Response (200 OK)

{
  "result": "yes",
  "current_api_version": "1.0"
}

Error Responses

Error CodeHTTP StatusMessageCause
APP_ERROR_INPUT_INVALID (1605)400"An invalid token was supplied, valid token required to remove 2Factor."Invalid token format
APP_NOT_ACCEPTED (1606)406"The supplied token failed to authenticate."Token verification failed
APP_INTERNAL_ERROR (1600)500"2Factor could not be removed, please contact support."Internal removal failure

Notes


2FA Code Delivery Endpoints

Request a 2FA code via different channels. All require auth (accepts user, twofactor, or admin JWT scope).

GET /current/user/auth/2factor/send/sms/

Send code via SMS

GET /current/user/auth/2factor/send/call/

Send code via voice call

GET /current/user/auth/2factor/send/whatsapp/

Send code via WhatsApp

Success Response (202 Accepted)

{
  "result": "yes",
  "current_api_version": "1.0"
}

Failure Response (406 Not Accepted)

{
  "result": "no",
  "current_api_version": "1.0"
}

Error Responses

Error CodeHTTP StatusMessageCause
APP_AUTH_INVALID (1650)401"Your credentials were not supplied or invalid."Invalid JWT
APP_AUTH_INVALID (1650)401"The scope of your credentials are not sufficient."Wrong JWT scope
APP_NOT_ACCEPTABLE (1606)406"2Factor is not enabled."2FA not configured on account

Notes


Complete 2FA Flows

Complete 2FA Login Flow

1. GET /current/user/auth/
   - Send email:password via HTTP Basic Auth
   - Response includes "2factor": true and limited-scope auth_token

2. GET /current/user/auth/2factor/send/sms/  (or /call/ or /whatsapp/)
   - Request a fresh 2FA code
   - Uses the limited-scope (twofactor) JWT

3. POST /current/user/auth/2factor/auth/{code}/
   - Submit the 2FA code
   - Receive a new JWT with full "user" scope
   - Use this token for all subsequent requests

Complete 2FA Setup Flow

1. POST /current/user/auth/2factor/{channel}/
   - Choose channel: sms, call, whatsapp, or totp
   - Phone number must be configured on account (for non-TOTP)
   - State becomes "unverified"
   - For TOTP: receive binding_uri for QR code

2. Receive code via selected channel (or scan QR code for TOTP)

3. POST /current/user/auth/2factor/verify/{code}/
   - Submit the verification code
   - State becomes "enabled"
   - 2FA is now active on the account

Complete 2FA Removal Flow

1. DELETE /current/user/auth/2factor/{code}/
   - Must provide valid 2FA code if state is "enabled"
   - Can remove without code if state is "unverified"
   - 2FA is fully removed from the account

Search for users by name or email across contacts and the platform user directory.

Auth: Required (JWT)

Query Parameters

ParameterTypeRequiredDescription
search string Yes Search term. Matches against user names and email addresses. Must not be blank.

Request Example

curl -X GET "https://api.fast.io/current/users/search/?search=john" \
  -H "Authorization: Bearer {jwt_token}"

Success Response (200 OK)

{
  "result": "yes",
  "response": {
    "contacts": {
      "john.doe@example.com": "John Doe",
      "jane.johnson@example.com": "Jane Johnson"
    }
  },
  "current_api_version": "1.0"
}

Response Fields

FieldTypeDescription
response.contactsobjectMap of email address (key) to display name (value) for each matched user.

Error Responses

Error CodeHTTP StatusMessageCause
APP_AUTH_INVALID (1650)401"Authentication required"Missing or invalid JWT token
APP_ERROR_INPUT_INVALID (1605)400"This value should not be blank."Missing or empty search parameter
APP_INTERNAL_ERROR (1600)500"Internal error"Search backend unavailable

Notes

Response Envelope

Success

{"result": "yes", "current_api_version": "1.0", ...}

Error

{
  "result": "no",
  "error": {
    "code": 195654,
    "text": "Human-readable message",
    "documentation_url": "https://api.fast.io/llms.txt",
    "resource": "POST /current/user/"
  }
}

Common Error Codes

CodeNameHTTP Status
1600APP_INTERNAL_ERROR500 Internal Server Error
1605APP_ERROR_INPUT_INVALID400 Bad Request
1606APP_NOT_ACCEPTABLE406 Not Acceptable
1607APP_ERROR_INPUT_DUPLICATE / APP_EXISTS409 Conflict
1608APP_CONFLICT409 Conflict
1609APP_ERROR_NOT_FOUND / APP_MISSING404 Not Found
1610APP_ERROR_DELETE_ERROR500 Internal Server Error
1650APP_AUTH_INVALID401 Unauthorized
1651APP_REQUEST_TYPE400 Bad Request
1653APP_USER_NOT_FOUND404 Not Found
1671APP_ENHANCE_CALM429 Too Many Requests
1680APP_DENIED403 Forbidden
1681APP_RESTRICTED403 Forbidden
1682APP_LOCKED423 Locked
1690APP_SSO_ERROR_AUTH401 Unauthorized

Rate Limiting

Response headers: X-Rate-Limit-Available, X-Rate-Limit-Expiry, X-Rate-Limit-Max

When exceeded: HTTP 429 with error code 1671 (APP_ENHANCE_CALM).

ID Formats

Token Types

TypeFormatLifetimeUse
JWT (Basic Auth)RS256-signed JSON Web TokenConfigurable (default varies)General API access
JWT (OAuth)RS256-signed JSON Web Token1 hourOAuth-based API access
Refresh TokenOpaque string30 daysObtaining new access tokens (OAuth only)
API KeyAlphanumeric stringLong-lived (no expiry)Service-to-service communication

Security Best Practices

  1. Always use HTTPS for all API communication.
  2. Store refresh tokens and API keys securely (OS keychain, encrypted storage).
  3. Never log tokens in client-side logs or analytics.
  4. Rotate refresh tokens — always store the new token from a refresh response.
  5. Verify the state parameter in OAuth callbacks to prevent CSRF.
  6. Handle 401 responses by attempting a token refresh; if refresh fails, re-authenticate.
  7. Revoke tokens on logout by calling the revoke endpoint and clearing local storage.
↑ Back to top