accessToken (plain-text bearer token) and the resolved companyId that must be sent as the X-Company header on all subsequent requests.
Base URL https://api.genuka.com · Auth Authorization: Bearer <token> + X-Company: <companyId> · See Getting Started for shared conventions, pagination & error formats.
Endpoints at a glance
Authentication
GET /2023-11/auth/login
Redirects the browser to the configured frontend login page. This is a convenience redirect for web flows and does not return JSON. Clients integrating the API directly should use POST /2023-11/auth/login.
POST /2023-11/auth/login
Authenticate a user with their email and password. Returns a Passport bearer token and basic company context.
- Query parameters: none
- Request body:
Request example
200 OK
The companies array is only present when the user belongs to more than one company.
Error responses
401 Unauthorized— invalid email/password combination
GET /2023-11/auth/register
Redirects the browser to the configured frontend registration page. Not a JSON API endpoint.
POST /2023-11/auth/register
Register a new company and its first admin user in a single request. Creates the company, creates the user (role admin), queues a welcome notification, creates a trial subscription, and returns a bearer token.
- Request body:
Request example
200 OK
Same shape as POST /2023-11/auth/login:
400 Bad Request— missingcompanyoruserpayload, or missingcurrency_code409(surfaced as aBusinessException) — email already registered; returns the list of companies the existing user belongs to
POST /2023-11/auth/register-additional-company
Add a new company to an existing authenticated user. The user must already have a valid token. Creates the company, attaches the user as admin, creates a trial subscription, and issues a new token scoped to the new company.
Rate-limited to 5 requests per minute.
- Request body:
The user object (if sent) is silently ignored — the company is attached to the currently authenticated user.
Request example
200 OK
Use the returnedError responsesaccessTokenandcompanyIdfor all subsequent requests scoped to the new company.
400 Bad Request— missingcompanypayload orcurrency_code401 Unauthorized— no valid token provided
POST /2023-11/auth/login-with-pin
Authenticate using a company short code and numeric PIN. Tokens issued by this endpoint expire after 24 hours. Intended for point-of-sale and kiosk flows.
- Request body:
Request example
200 OK
TheError responsestoken.expires_atis set to 24 hours after issuance. Thecompaniesarray is included when the PIN user belongs to more than one company.
401 Unauthorized— invalid company code or PIN422 Unprocessable Entity—company_codedoes not exist in the database
POST /2023-11/auth/verify-company-code
First step of the PIN login flow. Validates a company short code and returns basic company information to display on the PIN entry screen.
Rate-limited to 5 requests per minute.
- Request body:
Request example
200 OK
422 Unprocessable Entity—company_codedoes not exist
POST /2023-11/auth/logout
Revokes the current access token and its refresh token. Requires a valid bearer token.
- Request body: none
200 OK
401 Unauthorized— token is missing or already revoked
POST /2023-11/auth/password/email
Sends a 6-digit OTP to the user’s email address to initiate the password reset flow.
- Request body:
Request example
200 OK
404 Not Found— no user with the given email500 Internal Server Error— mail delivery failure
POST /2023-11/auth/password/reset
Resets the user’s password using the OTP received by email. The OTP is single-use and expires after a fixed window.
- Request body:
Request example
200 OK
400 Bad Request— OTP is invalid or expired404 Not Found— no user with the given email422 Unprocessable Entity— validation failure (e.g. passwords do not match, OTP not exactly 6 chars)
Email Verification
These endpoints require a valid bearer token (middlewareauth:apikey,app,admin,developer).
POST /2023-11/auth/email/send-verification
Dispatches a new 6-digit OTP to the authenticated user’s email address. The job is queued and fires after the HTTP response is sent.
Rate-limited to 3 requests per minute.
- Request body: none
200 OK
401 Unauthorized— no valid token422 Unprocessable Entity— email is already verified500 Internal Server Error— failed to dispatch notification
POST /2023-11/auth/email/verify
Verifies the authenticated user’s email address using the OTP. The OTP is marked as used after a successful verification.
- Request body:
Request example
200 OK
401 Unauthorized— no valid token422 Unprocessable Entity— email already verified, or OTP is invalid/expired
User Profile
GET /2023-11/user
Returns the full profile of the authenticated user, including their active company, subscription status, permissions, and (if applicable) a list of all companies they belong to.
- Query parameters:
Request example
200 OK
Error responsescompaniesis only present whenhas_multiple_companiesistrue.subscriptionmay benullif no active subscription exists.
401 Unauthorized— missing or revoked token
GET /2023-11/user/companies
Returns the list of all companies the authenticated user belongs to, ordered by most recently used.
Request example
200 OK
401 Unauthorized— missing or revoked token
PUT /2023-11/user/metadata
Merges the supplied key/value pairs into the authenticated user’s metadata JSON column. Existing keys not in the request body are preserved. Keys named metadata or anonymous in the request body are ignored.
- Request body: Any flat JSON object. All top-level keys (except
metadataandanonymous) are merged into the stored metadata.
200 OK
Returns a UserResource object (same shape as a user in a list response — see GET /2023-11/user for the company-context variant):
401 Unauthorized— missing or revoked token
POST /2023-11/user/set-pin
Sets or replaces the authenticated user’s 4-digit numeric PIN. The PIN is stored hashed and enables PIN-based login via POST /2023-11/auth/login-with-pin.
- Request body:
Request example
200 OK
401 Unauthorized— missing or revoked token422 Unprocessable Entity— PIN is not exactly 4 digits, contains non-numeric characters, or confirmation does not match
POST /2023-11/user/switch-company
Switches the authenticated user’s active company. Resolves effective permissions for the new company (role defaults merged with per-user overrides), syncs Spatie permissions, updates last_used_at on the pivot, revokes all existing tokens, and issues a new token scoped to the target company’s permissions.
- Request body:
Request example
200 OK
Replace theError responsesAuthorizationheader with the newaccessTokenand updateX-Companyto the newcompanyIdfor all subsequent requests.
401 Unauthorized— missing or revoked token403 Forbidden— the user does not belong to the requested company422 Unprocessable Entity—company_idmissing
POST /2023-11/user/refresh-token
Re-issues the user’s token with the current permissions stored in the database, without requiring a full re-login. Useful when server-side permissions or the subscription plan have changed. All existing tokens are revoked and replaced.
- Request body: none
200 OK
401 Unauthorized— missing or revoked token
Invitations
Invitation endpoints are public — they do not requireAuthorization or X-Company headers. The invitation token is a 64-character random string delivered via email. Invitations expire 7 days after being issued.
GET /2023-11/invitations
Retrieve invitation details to display on the acceptance screen. Validates the token and checks expiry before returning.
- Query parameters:
Request example
200 OK
404 Not Found— token not found or invitation already accepted/declined410 Gone— invitation is more than 7 days old422 Unprocessable Entity—tokenquery parameter is missing
POST /2023-11/invitations/accept
Accept a pending company invitation. Updates the pivot status to accepted, records accepted_at, attaches any pre-granted shops to the user, and clears the invitation token.
- Request body:
Request example
200 OK
404 Not Found— token not found or invitation is not inpendingstatus410 Gone— invitation has expired (older than 7 days)422 Unprocessable Entity—tokenfield missing
POST /2023-11/invitations/decline
Decline a pending company invitation. The pivot row is deleted permanently.
- Request body:
Request example
200 OK
404 Not Found— token not found or invitation is not inpendingstatus422 Unprocessable Entity—tokenfield missing
