Submit Login
Submit credentials to a login flow to authenticate a user with password, passkey, social login, or MFA.
Endpoint
POST /v1/flows/login/{flow_id}:submitBase URL: https://api-id.avnology.net
Authentication: None required (public endpoint, CSRF token in body)
Submits user credentials to an active login flow. The response is one of three outcomes:
- Session created -- login succeeded, session token returned
- Continue flow -- validation error or MFA challenge, updated UI returned
- Redirect -- external IdP or OAuth consent required
Request
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
flow_id | string | Yes | The login flow ID from Create Login Flow |
Headers
| Header | Required | Description |
|---|---|---|
Content-Type | Yes | application/json |
Body
The body structure depends on the authentication method:
Password Login
{
"method": "password",
"body": {
"identifier": "[email protected]",
"password": "SecureP@ssw0rd!",
"csrf_token": "dG9rZW4tYWJjMTIz..."
}
}Social Login (OIDC)
{
"method": "oidc",
"body": {
"provider": "google",
"csrf_token": "dG9rZW4tYWJjMTIz..."
}
}Passkey / WebAuthn
{
"method": "webauthn",
"body": {
"webauthn_login": "{\"id\":\"abc...\",\"rawId\":\"...\",\"response\":{...},\"type\":\"public-key\"}"
TOTP (MFA step)
{
"method": "totp",
"body": {
"totp_code": "123456",
"csrf_token": "dG9rZW4tYWJjMTIz..."
}
}Passwordless Code (email or SMS OTP)
{
"method": "code",
"body": {
"code": "847291",
"csrf_token": "dG9rZW4tYWJjMTIz..."
}
}Example Request (Password)
curl -X POST "https://api-id.avnology.net/v1/flows/login/f1a2b3c4-d5e6-7890-abcd-ef1234567890:submit" \
-H "Content-Type: application/json" \
-d '{
"method": "password",
"body": {
"identifier": "[email protected]",
"password": "SecureP@ssw0rd!",
"csrf_token": "dG9rZW4tYWJjMTIz..."
}
}'Response
Success -- Session Created
When login succeeds, a session is created:
{
"session": {
"id": "ses_1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"token": "avnl_ses_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0",
"expires_at": "2026-04-09T12:00:00Z",
"identity": {
"id": "usr_4f18acec-2712-4be7-a9af-b063b4f6deba",
"email": "[email protected]",
"first_name": "Jane",
"last_name": "Smith"
Store the token securely and use it as a Bearer token for subsequent requests.
Continue Flow -- MFA Required
If the user has MFA enabled, the flow continues with an MFA challenge:
{
"continue_flow": {
"id": "f1a2b3c4-d5e6-7890-abcd-ef1234567890",
"type": "login",
"state": "passed_challenge",
"active": "totp",
"ui": {
"action": "https://api-id.avnology.net/v1/flows/login/f1a2b3c4-d5e6-7890-abcd-ef1234567890:submit",
"method": "POST",
"nodes": [
Re-render the form with the updated UI nodes and submit again with the TOTP code.
Continue Flow -- Validation Error
If credentials are invalid:
{
"continue_flow": {
"id": "f1a2b3c4-d5e6-7890-abcd-ef1234567890",
"type": "login",
"state": "choose_method",
"ui": {
"action": "https://api-id.avnology.net/v1/flows/login/f1a2b3c4-d5e6-7890-abcd-ef1234567890:submit",
"method": "POST",
"nodes": [
"... same nodes as before ..."
],
"messages"
Display the messages to the user and let them try again.
Redirect -- External IdP
For social login, the response contains a redirect URL:
{
"redirect_to": "https://accounts.google.com/o/oauth2/v2/auth?client_id=...&redirect_uri=..."
}Navigate the user's browser to this URL. After authenticating with the external provider, they will be redirected back to complete the flow.
Errors
| Status | Code | Description |
|---|---|---|
| 400 | AVNOLOGY_AUTH_009 | Flow has expired -- create a new one |
| 400 | AVNOLOGY_AUTH_008 | CSRF token is missing or invalid |
| 401 | AVNOLOGY_AUTH_001 | Invalid credentials (returned in flow UI messages, not as HTTP error) |
| 403 | AVNOLOGY_AUTH_002 | Account is disabled |
| 403 | AVNOLOGY_AUTH_003 | Account is locked |
| 403 | AVNOLOGY_AUTH_022 | SSO is required for this organization |
| 429 | AVNOLOGY_AUTH_021 | Rate limit exceeded |
Code Examples
JavaScript (fetch)
async function submitLogin(flowId, email, password, csrfToken) {
const response = await fetch(
`https://api-id.avnology.net/v1/flows/login/${flowId}:submit`,
{
method: 'POST',
headers: { 'Content-Type'
Python (httpx)
import httpx
def submit_login(flow_id: str, email: str, password: str, csrf_token: str) -> dict:
response = httpx.post(
f"https://api-id.avnology.net/v1/flows/login/{
Go (net/http)
func submitLogin(ctx context.Context, flowID, email, password, csrfToken string) (*AuthFlowResult, error
Related
- Create Login Flow -- initiate a login flow
- Get Session -- validate the returned session
- Create Recovery Flow -- forgot password
- SDK:
client.auth.login({ email, password })(TypeScript)