Login
Overview
Authenticates an email/password credential. On success, it issues a Passport bearer token plus the user, company, theme, white-label and (for account companies) plan context. Several cases are rejected before a token is issued. These are locked accounts, SSO-only accounts (sso_required), inactive/unverified users, users with no company, and companies with bundle_id < 1.
Prerequisites
- No authentication — this endpoint is public.
Base URL
| Environment | URL |
|---|---|
| Production | https://production-api.shoutaboutus.com |
| Development | https://development-api.shoutaboutus.com |
Endpoint
POST /api/v1/login
Authentication
-
No bearer token required — this is a public endpoint.
-
Who can call it: Any user (Partner, Account, or other roles).
-
Public route (no authentication); throttled at 10/min per IP.
-
No partner/account scoping — it authenticates any user regardless of role.
-
The returned account's
bundle_id(1=partner, 2=location, 3=account) tells the SPA which role logged in. -
The endpoint validates the
refererhost against allowed/white-label hosts viaallowHost.
Rate limit
- 10 requests/min per IP.
Request body
- Body:
| Field | Type | Required | Description |
|---|---|---|---|
email | string | conditional | email:rfc, max 255. Required unless code is sent. |
password | string | conditional | max 100. Required unless code is sent. |
code | string | no | Admin-issued partner-impersonation code; when sent, email/password are not required. |
rememberMe | boolean | no | nullable; passed for long-lived session |
{
"email": "[email protected]",
"password": "<your password>",
"rememberMe": false
}Response
data.status(string) —"success"data.token(string) — Passport access tokendata.user(object) —id,username,email,inactive_at(nullable),email_verified_at,phone_number,first_name(person.firstname),last_name(person.lastname),title,role(person.role or"User"),total_location(count of stores reachable by the user)data.company(object) —id,name,bundle_id, plus appendedenable_insight_report(0/1),enable_competitive_analysis(0/1),dormant_accounts_enabled(0/1),companyindustry_id,company_industry(id/name),is_sub_partner(0/1), and includedcompany_option(company_id,who_will_pay,enable_generic_alert,enable_insight_report,enable_competitive_analysis)data.theme_options(string) — JSON stringdata.white_label(object) —logo,white_url,favicon,title,status,login_logo,company_id,email_templates_enableddata.plan(object|null) — only populated whencompany.bundle_id == 3(account). The assigned plan (id,plan_name,status,plan_type,enforcement_mode,is_admin_managed) withfeatures(id,plan_id,feature_name,enabled,hard_stop). Null otherwise.
Error cases (not {data}): 401 "Invalid email or password!" / locked-account message; 403 SSO-required ({sso_required:true, sso_url}) or no-company; 400 white-label not allowed / inactive / email not verified / subscription not active.
200 Success · 200
200{
"data": {
"status": "success",
"token": "<access-token>",
"user": {
"id": 8,
"username": "[email protected]",
"email": "[email protected]",
"first_name": "HiPages",
"last_name": "Admin",
"role": "Owner",
"total_location": 6
},
"company": {
"id": 9,
"name": "HiPages",
"bundle_id": 1,
"companyindustry_id": 7,
"company_industry": { "id": 7, "name": "Trades & Services" },
"is_sub_partner": 0
}
}
}401 Invalid credentials · 401
401{
"status": "error",
"message": "Invalid email or password!",
"errors": []
}Errors
| Status | Meaning |
|---|---|
400 | The request was rejected — the response explains why |
401 | Invalid email or password! (or the locked-account message) |
403 | The account must sign in via SSO (sso_required), or the user has no company |
422 | The request failed validation — the response names the fields |
500 | Unexpected server error |
Example request
curl --request POST \
--url "https://production-api.shoutaboutus.com/api/v1/login" \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{"email": "[email protected]", "password": "<your password>", "rememberMe": false}'Updated 10 days ago
