Auth
Authentication, registration, verification initiation, password reset, and logout.
Fangate uses Laravel Sanctum bearer tokens for authenticated API calls.
Base URLs:
- Production:
https://fangate.info/api - Development:
https://fangate.co/api
Response conventions
Most auth endpoints return the standard API wrapper:
{
"success": true,
"errors_message": null,
"data": {}
}Validation failures usually return:
{
"success": false,
"errors_message": "Human readable validation message",
"data": null
}See also Error Handling.
POST /api/register
Create a new creator account and return an access token plus the current user snapshot.
- Auth required: No
- Roles: Public
- Content type:
application/json
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
email | string | Yes | Must be unique among non-deleted users and pass trusted-email validation. |
password | string | Yes | Uses Laravel password defaults. |
first_name | string | Yes | Max 255 chars. |
last_name | string | Yes | Max 255 chars. |
birth_date | string | Yes | Format YYYY-MM-DD, must be 18+. |
currency_id | integer | No | If omitted, backend resolves currency from invite context or default DB currency. |
bank_data | object | No | Flexible payout fields; see Users. |
address | string | No | Required when bank details are supplied. |
master_id | integer | No | Referrer user id. Mutually exclusive with invite_code. |
fee_percentage | number | No | Max 10. Used with referral flows. |
invite_code | string | No | Mutually exclusive with master_id. |
is_adult_content | boolean | No | Default creator preference. |
is_verif_age | boolean | No | Default creator preference. |
Important validation and side effects
invite_codeandmaster_idcannot be sent together.fee_percentagecannot exceed10.- If
master_idis used, the affiliate currency must match the registering user's currency context. - When referral or payout setup requires it, backend may create Stripe onboarding data and include a
stripe_urlin the returned user resource.
Example request
curl -X POST https://fangate.info/api/register \
-H "Content-Type: application/json" \
-d '{
"email": "creator@example.com",
"password": "SecurePass123",
"first_name": "Alyssa",
"last_name": "Creator",
"birth_date": "1998-05-12",
"currency_id": 1,
"is_adult_content": true,
"is_verif_age": false
}'Success response example
{
"success": true,
"errors_message": null,
"data": {
"user": {
"id": 7,
"type": "business",
"email": "creator@example.com",
"first_name": "Alyssa",
"last_name": "Creator",
"birth_date": "1998-05-12",
"stripe_url": null,
"fee": {
"percentage": 4
},
"bank_data": null,
"address": null,
"is_verified": false,
"veriff_first_name": null,
"veriff_last_name": null,
"veriff_is_matched": null,
"is_adult_content": true,
"is_verif_age": false,
"is_epoch_enabled": false,
"currency_id": 1
},
"token": "7|sanctum-token"
}
}Error examples
Trusted email / duplicate email:
{
"success": false,
"errors_message": "The email has already been taken.",
"data": null
}Invalid invite combination:
{
"success": false,
"errors_message": "The invite code field prohibits master id.",
"data": null
}POST /api/login
Authenticate an existing user and return a new Sanctum token.
- Auth required: No
- Roles: Public
- Content type:
application/json
Request body
| Field | Type | Required |
|---|---|---|
email | string | Yes |
password | string | Yes |
Success response example
{
"success": true,
"errors_message": null,
"data": {
"user": {
"id": 7,
"email": "creator@example.com",
"is_verified": true
},
"token": "7|sanctum-token",
"account_group": {
"role": "master",
"master": null,
"linked_accounts": [
{
"id": 12,
"child_user_id": 42,
"email": "child@example.com",
"display_name": "Child Creator",
"currency_id": 1,
"currency_code": "EUR",
"linked_at": "2026-05-18T12:00:00+00:00"
}
]
}
}
}account_group is also returned from POST /api/register, GET /api/user, and each row of POST /api/login/batch (data.sessions[].account_group).
| Field | Type | Notes |
|---|---|---|
role | string | standalone (no links), master (manages linked children), or child (linked under a master). |
master | object or null | Present for child only: summary of the owning master account (user_id, email, display_name, currency fields). |
linked_accounts | array | Present for master only: persisted child accounts (no tokens). Empty for standalone and child. |
This is separate from affiliate master_slave relationships.
Error examples
Wrong credentials:
{
"success": false,
"errors_message": "Wrong email or password",
"data": null
}Deleted user / missing account:
{
"success": false,
"errors_message": "Wrong email or password",
"data": null
}POST /api/login/batch
Authenticate up to 10 creator accounts in a single request. Each successful row receives a new Sanctum token with name api (same semantics as POST /api/login). Failed rows are listed in data.failed without rolling back other successful logins.
- Auth required: No
- Roles: Public
- Content type:
application/json - Rate limiting: per-IP limiter
creator-login-batch(see backendAppServiceProvider)
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
accounts | array | Yes | Min 1, max 10 items. |
accounts[].email | string | Yes | Creator email. |
accounts[].password | string | Yes | Account password. |
Success response example
{
"success": true,
"errors_message": null,
"data": {
"sessions": [
{
"email": "a@example.com",
"user": { "id": 1, "email": "a@example.com" },
"token": "10|sanctum-token-a"
}
],
"failed": [
{
"email": "b@example.com",
"message": "Wrong email or password"
}
]
}
}GET /api/user/sessions
List active app sessions for the current creator: Sanctum personal access tokens whose name is api. Integration API keys (fangate-api-key:*) are not included.
- Auth required: Yes
- Roles: Authenticated creator (not when using a generated API key for account settings; same middleware as
GET /api/user)
Success response example
data is an array of session objects:
| Field | Type | Notes |
|---|---|---|
id | integer | Token row id; use with DELETE /api/user/sessions/{tokenId}. |
last_used_at | string or null | ISO 8601 when known. |
created_at | string or null | ISO 8601 when known. |
is_current | boolean | true for the token used on this request. |
{
"success": true,
"errors_message": null,
"data": [
{
"id": 42,
"last_used_at": "2026-05-10T12:00:00+00:00",
"created_at": "2026-05-01T08:00:00+00:00",
"is_current": true
}
]
}DELETE /api/user/sessions/
Revoke one app session by token id (from GET /api/user/sessions). Only tokens named api owned by the current user can be revoked.
- Auth required: Yes
- Roles: Authenticated creator (not when using a generated API key for account settings)
Path parameters
| Parameter | Type | Required |
|---|---|---|
tokenId | integer | Yes |
Success response example
{
"success": true,
"errors_message": null,
"data": "Session revoked"
}Error example
404 when the id is not an api session for this user:
{
"success": false,
"errors_message": "Session not found",
"data": null
}Linked creator accounts (master / child)
Persisted account groups for the creator account switcher. Relationships survive logout, browser reset, and device changes. Authorization is enforced on the backend — child accounts cannot see sibling accounts or manage the group.
| Method | Path | Auth | Who |
|---|---|---|---|
GET | /api/user/linked-accounts | Bearer | Master: full list in account_group. Child / standalone: empty linked_accounts. |
POST | /api/user/linked-accounts | Bearer | Master or standalone only. Body: { "email", "password" } for the child account to link. Max 10 children per master. |
DELETE | /api/user/linked-accounts/{childUserId} | Bearer | Master only. Removes one persisted link. |
POST | /api/user/linked-accounts/{childUserId}/session | Bearer | Master only. Returns data.user + fresh data.token for the child (for switching without storing the child password client-side). |
Child accounts receive 403 on link/unlink/session routes. A child account can only belong to one master (child_user_id is unique in account_group_members).
POST /api/user/linked-accounts — success example
{
"success": true,
"errors_message": null,
"data": {
"linked_account": {
"id": 12,
"child_user_id": 42,
"email": "child@example.com",
"display_name": "Child Creator",
"currency_id": 1,
"currency_code": "EUR",
"linked_at": "2026-05-18T12:00:00+00:00"
},
"account_group": {
"role": "master",
"master": null,
"linked_accounts": []
}
}
}Common validation errors (422)
| Message | Cause |
|---|---|
| Child accounts cannot manage linked accounts. | Authenticated user is a child. |
| This account is already linked to another master account. | Child is already in another group. |
| This account already manages other linked accounts and cannot be added as a child. | Target user is already a master. |
| Maximum number of linked accounts reached. | More than 10 children. |
| Wrong email or password | Child credentials invalid when linking. |
POST /api/user/email/verify
Start the email verification / pre-registration flow.
- Auth required: No
- Roles: Public
- Content type:
application/json
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
email | string | Yes | Must be unique in users.email. |
master_id | integer | No | Optional affiliate owner. |
fee_percentage | number | No | Optional affiliate fee override, max 10. |
Request source behavior
This endpoint is wrapped in DetectRequestSource middleware. Backend stores whether the request came from web/mobile context using request source detection and the generated app link.
Success response example
{
"success": true,
"errors_message": null,
"data": "Mail was sent"
}Side effects
- Creates or updates an
AppLinkwith theEMAIL_VERIFIEDaction. - Stores the request source flag (
is_web) inside app-link params when available. - Carries affiliate metadata when present.
POST /api/user/password/reset
Send a password reset email.
- Auth required: No
- Roles: Public
- Content type:
application/json
Request body
| Field | Type | Required |
|---|---|---|
email | string | Yes |
Important behavior
This endpoint is intentionally non-enumerating:
- it returns success even if the email is not found
- it only dispatches the actual reset email when a matching user exists
Success response example
{
"success": true,
"errors_message": null,
"data": "Mail was sent"
}PATCH /api/user/password
Change the authenticated user's password.
- Auth required: Yes
- Roles: Authenticated creator
- Content type:
application/json
Request body
| Field | Type | Required |
|---|---|---|
password | string | Yes |
Success response example
{
"success": true,
"errors_message": null,
"data": {
"user": {
"id": 7,
"email": "creator@example.com"
}
}
}POST /api/logout
Invalidate the current access token and optionally remove an FCM token.
- Auth required: Yes
- Roles: Authenticated creator
- Content type:
application/json
Query/body inputs
| Field | Type | Required | Notes |
|---|---|---|---|
fcm_token | string | No | If sent, backend removes the matching FCM token before deleting the current auth token. |
Success response example
{
"success": true,
"errors_message": null,
"data": "Logged out"
}Authentication flow examples
1. Creator registration and email verification
POST /api/user/email/verify- user receives email and follows the app link
POST /api/register- client stores returned Sanctum token
GET /api/userto refresh current user profile
2. Existing creator login
POST /api/login- store bearer token
- call authenticated endpoints with
Authorization: Bearer {token}
2b. Multi-account (account switcher) backend flow
POST /api/login/batchwith multiple{ email, password }pairs, or repeatedPOST /api/loginper account.- Store one bearer token per creator (e.g. keyed by
user.id). Switching accounts means sendingAuthorization: Bearer {that account's token}. - Optional:
GET /api/user/sessions/DELETE /api/user/sessions/{tokenId}to list or revoke app sessions for the currently authenticated user only. - Combined KPIs across several creators:
POST /api/dashboard/summary/aggregate(see Wallet); pass sibling tokens inadditional_tokenswhile authenticating with the primary account’s token.
3. Password reset
POST /api/user/password/reset- user receives reset email if account exists
- user completes reset outside the API flow documented here
Related
- Authentication
- Users
- Wallet (dashboard summary and aggregate KPIs)
- Verification