Developer dashboard

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:

http
x-api-key: YOUR_SECRET_API_KEY
Content-Type: application/json
  • x-api-key is the primary header. The gateway also accepts api-key, Authorization: <key> / Authorization: Bearer <key>, or apiKey / api_key in the JSON body, for older plugins.
  • Merchant-scoped keys resolve tenant and merchant from the key. X-Tenant-ID is optional and ignored on /api/v1/public/* — the key's tenant always wins. (On Admin API routes an X-Tenant-ID you send must be valid, or the request fails with 404 TENANT_NOT_FOUND.)
  • ERP / tenant-scoped keys (lv_erp_…) take the merchant from X-Merchant-ID, or merchantId in 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 an Origin or X-Merchant-Origin header 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
json
{
  "success": false,
  "error": "API key validation failed",
  "message": "Unable to validate API key. Please try again."
}

Step 1: Test connection#

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

bash
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)#

  1. Log in to the dashboard (Sandbox or Production host)
  2. Go to Settings → Developer & Integrations → API Keys
  3. 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
  4. 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#

POST/api/v1/public/accesstoken
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
bash
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"
  }'
json
{
  "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": []
  }
}
  • expiresIn is 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 with otpCode.
  • 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 returns 429 RATE_LIMITED.

Refresh an access token#

POST/api/v1/public/refreshToken
bash
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#

http
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#

POST/api/v1/public/client-token

Requires x-api-key. The merchant is taken from the key (or X-Merchant-ID for ERP keys); no body is needed.

json
{
  "success": true,
  "data": {
    "clientToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "expiresIn": 900,
    "type": "client_token"
  }
}

Validate a client token#

POST/api/v1/public/validate-client-token

No API key required. Body: { "token": "<clientToken>" }.

json
{
  "success": true,
  "data": {
    "valid": true,
    "tenantId": "your-tenant",
    "merchantId": "550e8400-e29b-41d4-a716-446655440000",
    "expiresAt": "2026-08-10T09:29:02.000Z"
  }
}
  • 400 VALIDATION_ERROR — token missing.
  • 401 TOKEN_EXPIRED — invalid or expired (data.valid is false).
  • 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 }) — the
selectionToken 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
json
{
  "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 and
navigation, 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 — merchantId missing.

Refresh keeps the selected merchant#

POST /api/v1/auth/refresh re-issues the token for the merchant the session was scoped to, and
GET /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/:linkId
  • POST /api/v1/public/payment-links/:linkId/pay
  • GET /api/v1/public/invoices/link/:linkId
  • POST /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