docs(api): add V3 user actions section and clarify response shape
Added section 7 covering /v3/action/user/ endpoints: authenticate, verify_password, change_password, new_auth_key, email_auth_key_url — including the legacy→V3 migration table and auth key one-time-use behavior. Also clarified the response shape note to explicitly list all response types (GET single, GET list, POST create, PATCH, search) that use the V3 envelope. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -73,7 +73,7 @@ Modify data in the system.
|
||||
> [!IMPORTANT]
|
||||
> **V3 responses always use random string IDs — never database integers.**
|
||||
|
||||
After a successful `POST` create or any `GET`, the response contains:
|
||||
All V3 responses — `POST` create, `GET` single, `GET` list, search, and `PATCH` update — contain:
|
||||
|
||||
| Field | Type | Use |
|
||||
| :--- | :--- | :--- |
|
||||
@@ -262,7 +262,150 @@ Frontend guidance:
|
||||
|
||||
---
|
||||
|
||||
## 7. Event Exhibit Tracking Export (Leads Export)
|
||||
## 7. User Actions (`/v3/action/user/`)
|
||||
|
||||
Stateful user account operations that are not standard CRUD. All require `x-aether-api-key`.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **Migration from legacy `/user/*` routes:** The table below maps each legacy endpoint to its V3 replacement. Run both in parallel during transition; remove legacy routes once traffic logs confirm they are quiet.
|
||||
>
|
||||
> | Legacy | V3 Replacement |
|
||||
> |---|---|
|
||||
> | `GET /user/authenticate` | `POST /v3/action/user/authenticate` |
|
||||
> | `POST /user/verify_password` | `POST /v3/action/user/verify_password` |
|
||||
> | `PATCH /user/{id}/change_password` | `POST /v3/action/user/{id}/change_password` |
|
||||
> | `GET /user/{id}/new_auth_key` | `GET /v3/action/user/{id}/new_auth_key` |
|
||||
> | `GET /user/{id}/email_auth_key_url` | `GET /v3/action/user/{id}/email_auth_key_url` |
|
||||
> | `GET /user/lookup` | `POST /v3/crud/user/search` |
|
||||
> | `GET /user/lookup_email` | `POST /v3/crud/user/search` |
|
||||
> | `GET /user/lookup_username` | `POST /v3/crud/user/search` |
|
||||
|
||||
### A. Authenticate
|
||||
|
||||
Authenticate a user by **username + password** or **user_id + auth_key**.
|
||||
|
||||
- **Method:** `POST`
|
||||
- **Path:** `/v3/action/user/authenticate`
|
||||
- **Auth:** `x-aether-api-key` + `x-account-id` (scopes username lookups to the correct account)
|
||||
- **Security improvement:** Credentials are in the **POST body**, not query params — safe from URL logging.
|
||||
|
||||
**Request body:**
|
||||
```json
|
||||
{ "username": "scott", "password": "MyPassword123!" }
|
||||
```
|
||||
or:
|
||||
```json
|
||||
{ "user_id": "<user_id_random>", "auth_key": "<one_time_key>", "valid_email": true }
|
||||
```
|
||||
|
||||
- `valid_email` (optional `bool`): if `true`, marks `email_verified = true` on success.
|
||||
- `inc_user_role_list` (optional query param, default `false`): include role list in the returned user object.
|
||||
|
||||
**Response on success:** Full user object (same shape as `GET /v3/crud/user/{id}`).
|
||||
|
||||
**Errors:** `400` missing credentials, `403` wrong password or account disabled, `404` user not found.
|
||||
|
||||
> **Auth key flow:** Auth keys are one-time-use — the key is cleared from the DB immediately on successful authentication. Request a new one via `GET /v3/action/user/{id}/new_auth_key`.
|
||||
|
||||
---
|
||||
|
||||
### B. Verify Password
|
||||
|
||||
Check a user's current password without changing it.
|
||||
|
||||
- **Method:** `POST`
|
||||
- **Path:** `/v3/action/user/verify_password`
|
||||
- **Auth:** `x-aether-api-key` + `x-account-id`
|
||||
|
||||
**Request body:**
|
||||
```json
|
||||
{ "user_id": "<user_id_random>", "current_password": "MyPassword123!" }
|
||||
```
|
||||
or use `"username"` instead of `"user_id"` to look up by username within the account.
|
||||
|
||||
**Response:** `data: true` on match. `403` on mismatch, `404` if user not found.
|
||||
|
||||
---
|
||||
|
||||
### C. Change Password
|
||||
|
||||
Change a user's password. Optionally verify the current password first.
|
||||
|
||||
- **Method:** `POST`
|
||||
- **Path:** `/v3/action/user/{user_id}/change_password`
|
||||
- **Auth:** `x-aether-api-key` + `x-account-id`
|
||||
|
||||
**Request body:**
|
||||
```json
|
||||
{ "new_password": "NewPassword456!", "current_password": "MyPassword123!" }
|
||||
```
|
||||
|
||||
- `new_password` is required (minimum 10 characters).
|
||||
- `current_password` is optional. If provided, it is verified before the change is applied. Omit it for admin-driven resets.
|
||||
|
||||
**Response:** `data: true` on success. `403` if `current_password` provided but wrong.
|
||||
|
||||
---
|
||||
|
||||
### D. Generate New Auth Key
|
||||
|
||||
Generate a fresh one-time-use auth key for the user and write it to the DB.
|
||||
|
||||
- **Method:** `GET`
|
||||
- **Path:** `/v3/action/user/{user_id}/new_auth_key`
|
||||
- **Auth:** `x-aether-api-key` + `x-account-id`
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{ "data": { "auth_key": "<new_key>" } }
|
||||
```
|
||||
|
||||
The returned key can then be passed to `/authenticate` (as `auth_key`) or embedded in a login URL. The user record must have `allow_auth_key = true` for key-based authentication to work.
|
||||
|
||||
---
|
||||
|
||||
### E. Email Auth Key URL
|
||||
|
||||
Generate a new auth key and email a one-time login link to the user's email address.
|
||||
|
||||
- **Method:** `GET`
|
||||
- **Path:** `/v3/action/user/{user_id}/email_auth_key_url`
|
||||
- **Auth:** `x-aether-api-key` + `x-account-id`
|
||||
|
||||
**Query Parameters:**
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|---|---|---|---|
|
||||
| `root_url` | `string` | `null` | Base URL the login link is built from. |
|
||||
| `key_param_name` | `string` | `auth_key` | Query param name used for the auth key in the generated link. |
|
||||
|
||||
**Response:** `data: true` on success (email sent). `500` if delivery failed (check account email config and that the user account is enabled with `allow_auth_key = true`).
|
||||
|
||||
---
|
||||
|
||||
### F. User Lookups via V3 CRUD Search
|
||||
|
||||
The three legacy lookup routes (`lookup`, `lookup_email`, `lookup_username`) are replaced by standard V3 CRUD search:
|
||||
|
||||
```typescript
|
||||
// Look up by user_id (Vision ID)
|
||||
POST /v3/crud/user/search
|
||||
{ "and": [{ "field": "id_random", "op": "eq", "value": "<user_id>" }] }
|
||||
|
||||
// Look up by email
|
||||
POST /v3/crud/user/search
|
||||
{ "and": [{ "field": "email", "op": "eq", "value": "user@example.com" }] }
|
||||
|
||||
// Look up by username
|
||||
POST /v3/crud/user/search
|
||||
{ "and": [{ "field": "username", "op": "eq", "value": "scott" }] }
|
||||
```
|
||||
|
||||
Results are automatically scoped to the `x-account-id` provided in the request.
|
||||
|
||||
---
|
||||
|
||||
## 9. Event Exhibit Tracking Export (Leads Export)
|
||||
|
||||
Allows an exhibitor to download all lead-capture records for their exhibit as a CSV or XLSX file.
|
||||
|
||||
@@ -330,7 +473,7 @@ const url = URL.createObjectURL(blob);
|
||||
|
||||
---
|
||||
|
||||
## 8. Troubleshooting 403 Forbidden
|
||||
## 10. Troubleshooting 403 Forbidden
|
||||
|
||||
If you receive a 403 on a valid ID:
|
||||
1. Verify `x-aether-api-key` is correct.
|
||||
|
||||
Reference in New Issue
Block a user