> ## Documentation Index
> Fetch the complete documentation index at: https://ifemafia.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# POST /v1/auth/login — authenticate and receive a token

> Authenticate with email and password. Returns a JWT session token to use in the Authorization header for protected API calls.

Exchange a registered email and password for a signed JWT session token. Attach the returned token to every subsequent authenticated request via the `Authorization: Bearer <token>` header. Tokens are time-limited — when one expires, prompt the user to log in again to receive a fresh token.

## Endpoint

```
POST /v1/auth/login
```

## Authentication

None required. This is a public endpoint.

## Request Body

<ParamField body="email" type="string" required>
  The email address associated with the Axis account.
</ParamField>

<ParamField body="password" type="string" required>
  The account password.
</ParamField>

## Request Example

```json theme={null}
{
  "email": "dev@acme.io",
  "password": "sup3rS3cur3!"
}
```

## Response — 200 OK

A successful request returns HTTP `200` with a JSON body containing a JWT session token and the authenticated user record. Note that `token` lives directly inside `data`, alongside `user` — it is not nested inside `data.user`.

<ResponseField name="status" type="string">
  Always `"success"` for a successful response.
</ResponseField>

<ResponseField name="data" type="object">
  Container for the session token and authenticated user details.

  <Expandable title="data fields">
    <ResponseField name="data.token" type="string">
      A signed JWT session token. Include this in the `Authorization: Bearer <token>` header for all authenticated requests.
    </ResponseField>

    <ResponseField name="data.user" type="object">
      The authenticated user record.

      <Expandable title="user fields">
        <ResponseField name="data.user.id" type="string">
          Unique UUID for the user account.
        </ResponseField>

        <ResponseField name="data.user.email" type="string">
          The email address associated with the account.
        </ResponseField>

        <ResponseField name="data.user.accountType" type="string">
          The account type: `"developer"` or `"business"`.
        </ResponseField>

        <ResponseField name="data.user.businessId" type="string | null">
          UUID of the associated business entity when `accountType` is `"business"`. `null` for developer accounts.
        </ResponseField>

        <ResponseField name="data.user.createdAt" type="string">
          ISO 8601 timestamp of when the account was created.
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

```json theme={null}
{
  "status": "success",
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImU5YjFmMjAzLTQ4NzEtNGUwZS1hNmNkLTFkNzZkYmMxNjNmZiIsImVtYWlsIjoiZGV2QGFjbWUuaW8iLCJpYXQiOjE3NTMwODgwMDAsImV4cCI6MTc1MzE3NDQwMH0.dummysignature",
    "user": {
      "id": "e9b1f203-4871-4e0e-a6cd-1d76dbc163ff",
      "email": "dev@acme.io",
      "accountType": "developer",
      "businessId": null,
      "createdAt": "2026-07-21T09:00:00.000Z"
    }
  }
}
```

## Error Responses

### 400 — Validation Error

Returned when a required field is missing or malformed.

```json theme={null}
{
  "status": "error",
  "errors": [
    {
      "code": "invalid_type",
      "expected": "string",
      "received": "undefined",
      "path": ["password"],
      "message": "Required"
    }
  ]
}
```

### 401 — Invalid Credentials

Returned when the email does not exist or the password is incorrect. The response is intentionally generic to avoid leaking whether an email address is registered.

```json theme={null}
{
  "status": "fail",
  "message": "Invalid email or password"
}
```
