Authentication#
How to authenticate with the AuxCORE Public API and dashboard.
Overview#
| Integration type | Auth |
|---|---|
| Server / ERP | x-api-key on /api/v1/public/* (X-Merchant-ID too for ERP keys) |
| Website embed (SDK) | lpk_live_… public key in data-api-key — no secret in HTML |
| Dashboard admin | JWT via login or POST /api/v1/public/accesstoken |
API key types#
Create keys at Dashboard → Settings → Developer & Integrations → API Keys:
| Type | Prefix | Use |
|---|---|---|
| Secret | api-… |
Server-side REST (x-api-key header) |
| SDK embed | lpk_live_… |
Client-side auxVault.js only |
| ERP | lv_erp_… |
Tenant-wide ERP (send X-Merchant-ID per call) |
| Processing | lv_pk_… |
Per-merchant, per-gateway payment key (created by an administrator) |
| Token processing | ltk_… |
Server-side PCI token processing on the PCI server; requires an allow-list of server IPs (created by an administrator) |
Merchant users can create Secret and SDK embed keys for their own merchant (and its locations); the other types need an administrator. Secret keys are shown once; SDK embed keys can be viewed again on /settings/developer/api-keys.
Tenant ID is a slug like auxvault-prod or a UUID — visible in Settings.
Public API headers#
Every server request to /api/v1/public/* (except customer-facing payment-link pages) needs:
x-api-key: YOUR_SECRET_API_KEY
Content-Type: application/jsonx-api-keyis the primary header. The gateway also acceptsapi-key,Authorization: <key>/Authorization: Bearer <key>, orapiKey/api_keyin the JSON body, for older plugins.- Merchant-scoped keys resolve tenant and merchant from the key.
X-Tenant-IDis optional and ignored on/api/v1/public/*— the key's tenant always wins. (On Admin API routes anX-Tenant-IDyou send must be valid, or the request fails with404 TENANT_NOT_FOUND.) - ERP / tenant-scoped keys (
lv_erp_…) take the merchant fromX-Merchant-ID, ormerchantIdin the body or query string. - SDK embed keys (
lpk_live_…) are for the browser checkout SDK only — never for plugins or server code. Every request must carry anOriginorX-Merchant-Originheader that is on the key's allowed origins (the dashboard requires at least one).
API key errors#
These are returned by /api/v1/public/* before the request reaches a service. Note that error is a string here:
| Status | error |
Cause |
|---|---|---|
| 401 | API key required |
No key in any accepted location |
| 401 | API key validation failed |
Key unknown, deactivated or mistyped — this is what an invalid key returns today. Also returned if the key service is unreachable |
| 401 | Invalid API key |
Key rejected without an error status (rare) |
| 403 | Origin required |
SDK key with allowed origins, no Origin / X-Merchant-Origin header |
| 403 | Origin not allowed |
Origin not on the SDK key's allow-list |
| 403 | Insufficient permissions |
SDK key used on an internal/admin path |
{
"success": false,
"error": "API key validation failed",
"message": "Unable to validate API key. Please try again."
}Step 1: Test connection#
curl -X POST https://uat.auxcore.net/api/v1/public/testConnection \
-H "x-api-key: YOUR_API_KEY" \
-H "X-Tenant-ID: YOUR_TENANT_ID"Step 2: Process a payment#
Card data never goes to this endpoint directly: collect it with the PCI SDK (https://vault.auxcore.net/sdk/) or POST /api/v1/public/tokenize-card and send the returned pciToken. Raw CardNumber / CVV is rejected on Sandbox and Production with 400 PCI_SCOPE_VIOLATION.
curl -X POST https://uat.auxcore.net/api/v1/public/transaction \
-H "x-api-key: YOUR_API_KEY" \
-H "X-Tenant-ID: YOUR_TENANT_ID" \
-H "Content-Type: application/json" \
-d '{
"Amount": 10.00,
"SuggestedMode": "Card",
"pciToken": "pci_tok_8f2c1a9b7e4d",
"BillingCustomerName": "Test Customer"
}'Create API keys (dashboard)#
- Log in to the dashboard (Sandbox or Production host)
- Go to Settings → Developer & Integrations → API Keys
- Click New Key and pick what you are connecting: WooCommerce plugin or Your server or backend create a Secret key (
api-…); Website checkout (No-Code SDK) creates an SDK Embed key (lpk_live_…) and asks for the allowed origins - Copy the value — secret keys are shown once
JWT for dashboard operations#
To obtain a JWT for Admin API routes (/api/v1/*), call accesstoken with both your API key and user credentials. The user is looked up in the API key's tenant.
Get an access token#
| Body field | Type | Required | Description |
|---|---|---|---|
email |
string | Yes | User email (must be a valid email) |
password |
string | Yes | User password |
otpCode |
string | No | MFA code, on the second call when MFA is required |
deviceId |
string | No | Device identifier, used for trusted-device MFA |
trustDevice |
boolean | No | With deviceId, skip MFA on this device next time |
curl -X POST https://uat.auxcore.net/api/v1/public/accesstoken \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "admin@yourcompany.com",
"password": "your-password"
}'{
"success": true,
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "3f9c2b7e0d...",
"tokenType": "Bearer",
"expiresIn": 86400,
"user": {
"id": "550e8400-e29b-41d4-a716-446655440010",
"email": "admin@yourcompany.com",
"fullName": "Jane Admin",
"role": "merchant_owner",
"merchantId": "550e8400-e29b-41d4-a716-446655440000",
"mfaEnabled": false
},
"features": { "invoicing": true },
"navigation": []
}
}expiresInis in seconds (24 hours by default). Refresh tokens last 30 days.- If MFA applies, the first call returns
{ "mfaRequired": true, "mfaMethod": "email", "message": "...", "userId": "..." }instead of a token; repeat the call withotpCode. - If the user belongs to several merchants, it returns
{ "merchantSelectionRequired": true, "selectionToken": "...", "merchants": [...] }— see Multi-merchant sessions below. - Wrong credentials return
401 UNAUTHORIZED(Invalid credentials). After 10 failed attempts for one account in 15 minutes the call returns429 RATE_LIMITED.
Refresh an access token#
curl -X POST https://uat.auxcore.net/api/v1/public/refreshToken \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "refreshToken": "YOUR_REFRESH_TOKEN" }'Returns { "success": true, "data": { "token", "refreshToken", "tokenType": "Bearer", "expiresIn" } }. Refresh tokens are single-use: store the new refreshToken every time. Presenting an already-used refresh token returns 401 and signs out all of that user's sessions. A missing refreshToken returns 400 VALIDATION_ERROR.
Use the JWT on admin routes#
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...The tenant comes from the token. An expired token returns 401 TOKEN_EXPIRED; a malformed or forged one returns 401 INVALID_TOKEN.
Admin routes also accept a secret or ERP API key in x-api-key instead of a JWT. SDK embed keys are refused there with 403 FORBIDDEN.
SDK client tokens#
Short-lived tokens for client-side code that should not hold an API key.
Create a client token#
Requires x-api-key. The merchant is taken from the key (or X-Merchant-ID for ERP keys); no body is needed.
{
"success": true,
"data": {
"clientToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 900,
"type": "client_token"
}
}Validate a client token#
No API key required. Body: { "token": "<clientToken>" }.
{
"success": true,
"data": {
"valid": true,
"tenantId": "your-tenant",
"merchantId": "550e8400-e29b-41d4-a716-446655440000",
"expiresAt": "2026-08-10T09:29:02.000Z"
}
}400 VALIDATION_ERROR—tokenmissing.401 TOKEN_EXPIRED— invalid or expired (data.validisfalse).401 INVALID_TOKEN— a valid JWT that is not a client token.
The four token endpoints (accesstoken, refreshToken, client-token, validate-client-token) share one limit of 30 requests per 15 minutes per IP with field-config and the checkout-session endpoints; over it they return 429 RATE_LIMITED.
Multi-merchant sessions#
A user can belong to several merchants. The access token carries exactly one merchantId, and every
merchant-scoped call is answered for that merchant.
At login. When the user belongs to more than one merchant, POST /api/v1/auth/login returns{ merchantSelectionRequired: true, selectionToken, merchants[] } instead of a token. Complete the
login with POST /api/v1/auth/select-merchant (body { selectionToken, merchantId }) — theselectionToken is valid for 10 minutes.
After login. Use these two routes; both require Authorization: Bearer <jwt> and X-Tenant-ID.
GET /api/v1/auth/my-merchants#
Merchants the signed-in user can work in.
| Query | Default | Description |
|---|---|---|
includeDeviceStatus |
true |
Set false to skip the per-merchant device lookup |
{
"success": true,
"data": {
"currentMerchantId": "merchant_123",
"merchants": [
{
"merchantId": "merchant_123",
"companyName": "Acme Coffee",
"role": "merchant_admin",
"status": "active",
"deviceRegistration": {
"hasActiveDevice": true,
"activeDeviceCount": 1,
"device": {
"deviceId": "550e8400-e29b-41d4-a716-446655440001",
"deviceLabel": "Counter 1",
"tpnLast4": "4651",
"status": "ACTIVE",
"lastActiveAt": "2026-08-10T09:14:02.000Z"
}
}
}
]
}
}deviceRegistration reports whether this user already has an ACTIVE device registered at that
merchant — devices registered by other staff never count. It is a display hint for POS/mobile apps;GET /api/v1/device/session decides whether a
stored device token still works.
POST /api/v1/auth/switch-merchant#
Switch the active merchant without logging out. Body: { "merchantId": "merchant_456" }.
Returns the same shape as select-merchant: a new token, refreshToken, user, features andnavigation, scoped to the new merchant. Replace the stored access token with it.
401— the user has no access to that merchant, or the merchant is closed.400—merchantIdmissing.
Refresh keeps the selected merchant#
POST /api/v1/auth/refresh re-issues the token for the merchant the session was scoped to, andGET /api/v1/auth/me reports that same merchant. Refreshing no longer reverts a multi-merchant user
to their primary merchant.
Authentication summary#
| Use case | Headers |
|---|---|
| Public API (ERP, plugins) | x-api-key (+ X-Merchant-ID for ERP keys) |
| SDK embed in browser | data-api-key on script tag only |
| Admin API | Authorization: Bearer JWT (or x-api-key with a secret/ERP key) |
| accesstoken / refreshToken / client-token | x-api-key, JSON body |
| validate-client-token | JSON body only |
| my-merchants / switch-merchant | Authorization: Bearer JWT, X-Tenant-ID |
Customer-facing routes (no API key)#
These are called from hosted pay pages in the browser — no x-api-key:
GET /api/v1/public/payment-links/:linkIdPOST /api/v1/public/payment-links/:linkId/payGET /api/v1/public/invoices/link/:linkIdPOST /api/v1/public/checkout-sessions/:sessionId/pay
Security#
- Never commit API keys to git
- Never put
api-…secret keys in frontend JavaScript - Restrict SDK public keys with allowed origins on
/settings/developer/api-keys - Rotate keys after staff changes
Need help? Contact support@auxcore.net