Provider Login Endpoint
The Provider Login endpoint provisions or logs in an external provider user for the requesting partner, issues a 30-day Laravel Sanctum authentication token, and returns an optional partner redirect URL.
The endpoint supports two specification modes:
- Signed Provider Specification (Secure Mode): Uses RSA-SHA256 digital signature verification, custom security headers, and structured response envelopes.
- Standard / Legacy Provider Specification: Generic provider integration using standard payload fields and envelope formatting.
- Endpoint:
/api/v1/auth/provider-login - Method:
POST - Authentication:
Partner-Access-Token(Required for both modes).
Specification Modes Detection
The backend automatically detects the Signed Provider Specification if any of the following indicators are present in the request:
- Request header
X-Request-Signatureis present - Request header
X-Nonce-Idis present - Request body parameter
requestIdis present - Request body parameter
currencySupportis present
If none of these are present, the endpoint operates in Standard Provider Mode.
1. Signed Provider Specification (Secure Mode)
Request Headers
| Header | Type | Required | Description |
|---|---|---|---|
Partner-Access-Token | Base64 String | Yes | Partner B2B token identifying the partner account. |
Content-Type | String | Yes | Must be application/json. |
Accept | String | Yes | Must be application/json. |
X-Request-Signature | String | Optional* | RSA-SHA256 signature (Base64URL-encoded). Required when signature verification is enabled. |
X-Nonce-Id | String | Optional* | Unique random nonce string (e.g., 16-character hex string such as a37f219c05ee8144). |
X-Request-Time | String | Optional* | ISO 8601 timestamp with timezone offset, e.g. 2026-01-12T12:12:14+07:00. |
* When
X-Request-Signatureis sent,X-Nonce-IdandX-Request-Timemust also be provided to construct the string to be signed.
RSA Signature Specification
Signed provider requests use RSA-SHA256 digital signatures for end-to-end payload integrity and authenticity.
1. Content To Be Signed
<HTTP-METHOD> <Request-URI>
<X-Nonce-Id>.<X-Request-Time>.<Request-Body>
<HTTP-METHOD>: Uppercase HTTP method (e.g.,POST).<Request-URI>: Path of the endpoint (e.g.,/api/v1/auth/provider-login).\n: A single newline character separating the request line and the body metadata.<X-Nonce-Id>: Value from theX-Nonce-Idheader.<X-Request-Time>: Value from theX-Request-Timeheader.<Request-Body>: The raw JSON request body payload.
Example Content To Be Signed:
POST /api/v1/auth/provider-login
a37f219c05ee8144.2026-01-12T12:12:14+07:00.{"userId":"USER-1000123","userName":"John Doe","currencySupport":["LAK","THB","USD"]}
2. Signing & Verification
- Client: Signs
Content_To_Be_Signedwith the client RSA private key usingSHA256withRSA, encoded as Base64URL without padding (+→-,/→_, strip trailing=). - Server Verification: The server verifies the signature against the configured RSA public key. If verification fails, HTTP 200 with
INVALID_SIGNATUREis returned.
Signed Mode Payload Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
userId | String | Integer | Yes | Stable unique user identifier assigned by the provider. |
userName | String | Optional | User full name (e.g. "John Doe"). Automatically split into first_name and last_name if no explicit first name is provided. |
dob | String | Optional | Date of birth in YYYY-MM-DD format. |
currencySupport | Array of Strings | Optional | Currencies supported by the user, e.g. ["LAK", "THB", "USD"]. |
mobileNumber | String | Optional | User's mobile contact number. |
email | String | Optional | Real user email. If omitted or invalid, an auto-generated placeholder email is assigned with is_fake_email: true. |
requestId | String | Optional | Request or transaction tracking identifier from the provider. |
Sample Signed Request Payload
{
"requestId": "REQ-20260914-001",
"userId": "USER-1000123",
"userName": "John Doe",
"dob": "1995-06-15",
"currencySupport": ["LAK", "THB", "USD"],
"mobileNumber": "02055512345",
"email": "john.doe@example.com"
}
Signed Mode Response Format
Response Headers
Successful and failure responses from signed provider requests include signature headers:
| Header | Description |
|---|---|
Content-Type | application/json |
X-Nonce-Id | Server-generated 16-character hex nonce string. |
X-Response-Time | Server ISO 8601 timestamp with offset (e.g., 2026-09-14T12:08:00+07:00). |
X-Response-Signature | Base64URL-encoded RSA-SHA256 signature generated with the server's private key over the response content. |
Authorization | Plaintext Sanctum Bearer token for API client access (e.g., 2|sanctum-plain-text-token). |
Sample Signed Mode Success Response
{
"result": {
"resultStatus": "S",
"resultCode": "SUCCESS",
"resultMessage": "Success"
},
"miniAppUrl": "https://partner.example.com/callback?token=4XgY6...encryptedToken",
"is_fake_email": false
}
Field Descriptions
| Field | Type | Description |
|---|---|---|
result.resultStatus | String | S for success, F for failure. |
result.resultCode | String | Status code string (SUCCESS, INVALID_SIGNATURE, LOGIN_FAILED). |
result.resultMessage | String | Human-readable status message. |
miniAppUrl | String | null | Redirect URL with encrypted token to open partner application. null if partner has no acsr_domain configured. |
is_fake_email | Boolean | true if the account is using an auto-generated placeholder email; false if verified/real email. |
Error Responses
1. Invalid Signature
{
"result": {
"resultStatus": "F",
"resultCode": "INVALID_SIGNATURE",
"resultMessage": "The signature is invalid"
}
}
2. Login Failure
{
"result": {
"resultStatus": "F",
"resultCode": "LOGIN_FAILED",
"resultMessage": "Login failed, please try again later."
}
}
2. Standard / Legacy Provider Specification
This mode is used for standard partner integrations when signature headers or extended fields are not included.
Request Headers
| Header | Value | Required | Description |
|---|---|---|---|
Partner-Access-Token | Base64 String | Yes | Partner B2B token. |
Content-Type | application/json | Yes | |
Accept | application/json | Yes |
Payload Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
userId | String | Integer | Yes | Stable unique provider user ID. |
firstName | String | Yes | User first name. |
lastName | String | Optional | User last name. |
username | String | Optional | Display name. Defaults to a random 8-character string if omitted. |
dateOfBirth | String | Optional | Date in YYYY-MM-DD format. |
currencies | Array of Strings | Optional | Provider currency codes, e.g. ["USD", "THB"]. |
phonePrefix | String | Optional | Dial code such as +66. The leading + is stripped upon saving. |
phoneNumber | String | Optional | User telephone number. |
emailAddress | String | Optional | Valid email address. If omitted, a fake placeholder email is assigned. |
Sample Standard Payload
{
"userId": "USER-1000123",
"username": "johndoe",
"firstName": "John",
"lastName": "Doe",
"dateOfBirth": "1995-06-15",
"currencies": ["USD", "THB"],
"phonePrefix": "+66",
"phoneNumber": "800000000",
"emailAddress": "user@example.com"
}
Sample Standard Response
{
"result": 1,
"message": "success",
"data": {
"token": "2|sanctum-plain-text-token",
"expires_at": "2026-10-14T05:08:00.000000Z",
"redirect_url": "https://partner.example.com/callback?token=4XgY6...encryptedToken",
"is_fake_email": false
}
}
Response Headers
Authorization:2|sanctum-plain-text-token(Plaintext Sanctum Bearer token).
User Matching and Account Resolution
- User Lookup:
- The user record is matched by
partner_id, provider user type, andprovider_user_id = userId. - If an existing user under the same partner matches the supplied real email address, the system automatically links the provider account to that existing user.
- The user record is matched by
- Placeholder Fake Email:
- If no valid email is supplied:
- If the user account was previously verified with a real email (
is_fake_email == false), their real email is preserved. - Otherwise, an auto-generated placeholder email is assigned and flagged with
is_fake_email: true.
- If the user account was previously verified with a real email (
- If no valid email is supplied:
- Token Expiry:
- The returned Sanctum token is configured to expire in 30 days (
now()->addDays(30)).
- The returned Sanctum token is configured to expire in 30 days (
- Redirect / Launch URL Security:
miniAppUrl/redirect_urlis created using the partner's configuredacsr_domain.- The token query parameter is encrypted with AES-256-GCM using the partner secret (
partners.token). - The partner frontend decrypts the token using the same secret to obtain the plaintext Sanctum token.
Binding Real Email (Email OTP Verification)
When a user logs in without an email (is_fake_email: true), they can bind and verify a real email address through the companion OTP verification flow:
- Request Verification Code:
POST /api/v1/auth/send-email-otp- Dispatches a 6-digit numeric verification code to the target email.
- Verify Code & Bind Email:
POST /api/v1/auth/verify-email-otp- Verifies the OTP, updates the user's
email, setsis_fake_email: false, and marksemail_verified_at.
For detailed request and response specifications of this flow, see Provider Email OTP Verification.