Skip to content

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

Response conventions ​

Most auth endpoints return the standard API wrapper:

json
{
  "success": true,
  "errors_message": null,
  "data": {}
}

Validation failures usually return:

json
{
  "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
  • The address must have been confirmed first: the creator opens the link in the mail sent by POST /api/user/email/verify, otherwise 422 errors_code: email_not_confirmed. The creator's contract signature must have arrived (GET /api/registration/signature-status), otherwise 422 with a message on registration_signature_submission_id. A signature is used up only by a registration that succeeds. Step by step: Onboarding.

Request body ​

FieldTypeRequiredNotes
emailstringYesMust be unique among non-deleted users and pass trusted-email validation.
passwordstringYesUses Laravel password defaults.
first_namestringYesMax 255 chars.
last_namestringYesMax 255 chars.
birth_datestringYesFormat YYYY-MM-DD, must be 18+.
currency_idintegerNoThe payout currency, permanent once the account exists - send it; ids from GET /api/app-data (currencies[]). If omitted, backend resolves currency from invite context or default DB currency.
registration_legal_acceptedbooleanYestrue: the creator accepted the Terms of Service, Privacy Policy, Content Removal Policy and 18 USC 2257 statement (GET /api/app-data → registration.legal.documents).
content_display_consentbooleanSee notetrue: the creator's consent to the public display of their content, a checkbox of its own next to the legal acceptance (wording in GET /api/app-data → registration.content_display_consent.label). Registration screens should show the box and send the field once the creator ticks it. Required only when registration.content_display_consent.required is true - an admin switch, off in production (since 2026-09-28). When sent, it must be true either way. false - or a missing field while the switch is on - answers 422 with errors_code: content_display_consent_required (the code is set when this field is the first failure; otherwise the first failing field's code and message are returned). The consent is stored with its timestamp and the exact wording.
agency_invite_tokenstringNoRegistration through an agency invitation mail; cannot be combined with invite_code.
bank_dataobjectNoPayout fields; see Users. Optional on Fangate's own registration since 2026-10-08 (a collapsed tile on the currency step); the creator can also add the account under Payout settings before the first cashout.
country_codestringNoThe creator's country of residence, ISO 3166-1 alpha-2 (DE), validated against the platform's country list (since 2026-10-08). Fangate's own registration always sends it; it drives the VAT on Fangate's commission for private EU creators.
payout_methodstringNowire (default) or crypto - which saved details a payout uses; see Payout account.
tron_usdt_walletstringNoTRON (TRC-20) USDT address for crypto payouts: starts with T, 34 characters. Refused with 422 on another format, before the account is created. Optional even with payout_method: crypto - the payout then waits for the wallet.
addressstringNoRequired when bank details are supplied.
invite_codestringNoA referrer's invite code.
is_adult_contentbooleanNoDefault creator preference.
is_verif_agebooleanNoDefault creator preference.

Important validation and side effects ​

  • Rate limit: 5 a minute per address and IP, 15 a minute per IP.
  • When referral or payout setup requires it, backend may create Stripe onboarding data and include a stripe_url in the returned user resource.

Example request ​

bash
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 ​

json
{
  "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": 3
      },
      "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:

json
{
  "success": false,
  "errors_message": "The email has already been taken.",
  "data": null
}

Invalid invite combination:

json
{
  "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 ​

FieldTypeRequired
emailstringYes
passwordstringYes

Success response example ​

json
{
  "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).

FieldTypeNotes
rolestringstandalone, master, sub_account, or hybrid (see linked-account section).
masterobject or nullPresent for sub_account only: summary of one owning master (user_id, email, display_name, currency fields). If the user is linked under multiple masters, the API returns the first membership row only.
linked_accountsarraySub-accounts this user linked (master and hybrid). Empty for standalone and pure sub_account. Never includes siblings from another master’s group.

This is separate from affiliate master_slave relationships.

Error examples ​

Wrong credentials:

json
{
  "success": false,
  "errors_message": "Wrong email or password",
  "data": null
}

Deleted user / missing account:

json
{
  "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 backend AppServiceProvider)

Request body ​

FieldTypeRequiredNotes
accountsarrayYesMin 1, max 10 items.
accounts[].emailstringYesCreator email.
accounts[].passwordstringYesAccount password.

Success response example ​

json
{
  "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:

FieldTypeNotes
idintegerToken row id; use with DELETE /api/user/sessions/{tokenId}.
last_used_atstring or nullISO 8601 when known.
created_atstring or nullISO 8601 when known.
is_currentbooleantrue for the token used on this request.
json
{
  "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 ​

ParameterTypeRequired
tokenIdintegerYes

Success response example ​

json
{
  "success": true,
  "errors_message": null,
  "data": "Session revoked"
}

Error example ​

404 when the id is not an api session for this user:

json
{
  "success": false,
  "errors_message": "Session not found",
  "data": null
}

Linked creator accounts (master / sub-account) ​

Persisted directional links for the creator account switcher (master_user_id → child_user_id). Relationships survive logout, browser reset, and device changes. The same sub-account may appear under multiple masters (unique per master/sub-account pair). Authorization is enforced on the backend — a sub-account never receives another master’s linked list or siblings.

MethodPathAuthWho
GET/api/user/linked-accountsBearerReturns account_group for the current user (own linked_accounts only).
POST/api/user/linked-accountsBearerAny authenticated creator. Body: { "email", "password" } for the sub-account to link. Max 10 sub-accounts per linking account.
DELETE/api/user/linked-accounts/{childUserId}BearerRemoves one link created by the current user only.
POST/api/user/linked-accounts/{childUserId}/sessionBearerReturns data.user + fresh data.token only when the bearer directly linked that sub-account.

account_group.role values:

RoleMeaning
standaloneNo links as master or sub-account.
masterHas linked sub-accounts; not linked under anyone else.
sub_accountLinked under at least one master; has not linked others.
hybridBoth linked under a master and has its own linked sub-accounts.

POST /api/user/linked-accounts — success example ​

json
{
  "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) ​

MessageCause
Maximum number of linked accounts reached.More than 10 sub-accounts for this linking account.
Wrong email or passwordSub-account credentials invalid when linking.
You cannot link your own account.Target email is the same user as the bearer.
Linked account not found.Unlink or session for a child_user_id this master did not link.

POST /api/user/email/verify ​

Start the email verification / pre-registration flow.

  • Auth required: No
  • Roles: Public
  • Content type: application/json

Request body ​

FieldTypeRequiredNotes
emailstringYesMust be unique in users.email and not a disposable address.
invite_codestringNoA referrer's invite code.
return_urlstringNoPartners with a registration screen of their own: the https page the click on the mailed link lands on, with ?email=<address>&email_confirmed=1 appended; only on a domain registered with Fangate, otherwise 422 (errors_field: return_url). See Onboarding.

The click on the mailed link is what confirms the address; GET /api/registration/email-status?email= tells whether it happened (confirmed) or whether the mail is older than 48 hours (expired - request a new one; a click that is still valid survives a new mail). Rate limit: 3 a minute per address, 10 a minute per IP (registered partner servers 100).

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 ​

json
{
  "success": true,
  "errors_message": null,
  "data": "Mail was sent"
}

Side effects ​

  • Creates or updates an AppLink with the EMAIL_VERIFIED action.
  • 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 ​

FieldTypeRequired
emailstringYes

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 ​

json
{
  "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 ​

FieldTypeRequired
passwordstringYes

Success response example ​

json
{
  "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 ​

FieldTypeRequiredNotes
fcm_tokenstringNoIf sent, backend removes the matching FCM token before deleting the current auth token.

Success response example ​

json
{
  "success": true,
  "errors_message": null,
  "data": "Logged out"
}

Authentication flow examples ​

1. Creator registration and email verification ​

  1. POST /api/user/email/verify
  2. user receives email and follows the link (GET /api/registration/email-status reports the click)
  3. user signs the creator contract in the embedded signature form (GET /api/registration/signature-status reports it)
  4. POST /api/register with registration_legal_accepted: true and content_display_consent: true
  5. client stores returned Sanctum token
  6. GET /api/user to refresh current user profile

2. Existing creator login ​

  1. POST /api/login
  2. store bearer token
  3. call authenticated endpoints with Authorization: Bearer {token}

2b. Multi-account (account switcher) backend flow ​

  1. POST /api/login/batch with multiple { email, password } pairs, or repeated POST /api/login per account.
  2. Store one bearer token per creator (e.g. keyed by user.id). Switching accounts means sending Authorization: Bearer {that account's token}.
  3. Optional: GET /api/user/sessions / DELETE /api/user/sessions/{tokenId} to list or revoke app sessions for the currently authenticated user only.
  4. Combined KPIs across several creators: POST /api/dashboard/summary/aggregate (see Wallet); pass sibling tokens in additional_tokens while authenticating with the primary account’s token.

3. Password reset ​

  1. POST /api/user/password/reset
  2. user receives reset email if account exists
  3. user completes reset outside the API flow documented here

Fangate backend developer documentation