Skip to main content
Shogun protects every API call with a Bearer JWT. For server-to-server integrations you exchange a client_id and client_secret for a token that lasts one hour. A separate Dashboard API exists for browser and mobile sessions and uses email/password login instead. This page covers both flows, explains how to attach a token to requests, and shows you how to verify the HMAC-SHA256 signatures Shogun adds to outbound webhooks.

Two authentication flows

Shogun has two separate APIs with different credential types:
Integration APIDashboard API
Who uses itYour backend serverYour web or mobile app
Credentialsclient_id + client_secretEmail + password
Token endpointPOST /api/v1/security/api/generate_tokenPOST /api/v1/auth/web/login
Token typeBearer JWTBearer JWT (+ HTTP-only cookie)
Token TTL1 hourConfigurable
The rest of this page focuses on the Integration API, which is what you use for backend server-to-server calls.

Your API credentials

Find your credentials in Dashboard → Security → API Client.
FieldDescription
client_idPublic identifier for your business — safe to log
client_secretSecret key — treat like a password, never expose publicly
If your client_secret is ever compromised, rotate it immediately from the dashboard. The old secret is invalidated instantly. Rotation requires password confirmation.

Generating a token

Send your credentials to the token endpoint to receive a Bearer JWT:
curl -X POST https://api.shogun.io/api/v1/security/api/generate_token \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "your-client-id",
    "client_secret": "your-client-secret"
  }'
A successful response:
{
  "status": true,
  "response_code": "00",
  "message": "Token generated successfully",
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "expires_in": 3600
  }
}
Cache the token value server-side. Tokens expire after 3600 seconds (1 hour). Generate a new one before expiry rather than waiting for a 401 or response_code: "42" error on a live request.

Using the token

Pass the token as a Bearer value in the Authorization header on every authenticated request:
curl https://api.shogun.io/api/v1/account/api/fetch_customer_accounts \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Validating a token

Before making a sensitive request, you can confirm a cached token is still valid:
curl -X GET https://api.shogun.io/api/v1/security/api/validate_token \
  -H "Authorization: Bearer <your-token>"
A valid token returns token metadata including its issued_at and expires_at timestamps:
{
  "status": true,
  "message": "Token is valid",
  "data": {
    "username": "your-username",
    "client_id": "your-client-id",
    "authorities": ["TRANSACTION_READ", "TRANSACTION_WRITE"],
    "issued_at": "2024-01-15T10:30:00",
    "expires_at": "2024-01-16T10:30:00"
  }
}

Dashboard API auth

If you are building a web or mobile dashboard on top of Shogun, use the Dashboard API login endpoint instead. It accepts an email/password pair and returns a JWT you pass as a Bearer token on all /web/ endpoints:
curl -X POST https://api.shogun.io/api/v1/auth/web/login \
  -H "Content-Type: application/json" \
  -d '{ "email": "you@business.com", "password": "yourpassword" }'

Token lifecycle

client_id + client_secret

POST /api/v1/security/api/generate_token

  Bearer token (1h TTL)

  Use on all API calls

  Expires → generate a new one
Repeated failed authentication attempts trigger a temporary account lockout. Implement exponential backoff on 401 responses to avoid being locked out during token rotation.

Webhook signature verification

Shogun signs every outbound webhook payload with HMAC-SHA256 using your webhook secret. The signature is sent in the X-Shogun-Signature header in the format sha256=<hex-digest>. You must verify this signature before trusting or processing the event.
Always verify the signature before acting on a webhook payload. Skipping verification exposes your system to spoofed events.
import hmac
import hashlib

def verify_webhook(payload_body: bytes, signature_header: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        payload_body,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(f"sha256={expected}", signature_header)
Pass the raw request body as bytes, the X-Shogun-Signature header value, and your webhook secret. The function returns True only when the signatures match using a timing-safe comparison.
Use your framework’s raw body parser to read the request body before any JSON parsing. Many frameworks parse JSON by default and discard the raw bytes, which will break signature verification.