A Full Guide to API Keys and JWTs

SignStack uses a robust, modern authentication system for its API, designed to be both secure and developer-friendly. This guide explains the two core components: long-lived API Keys and short-lived JWT Access Tokens.

Understanding this system is crucial for securely integrating your application with the SignStack API.

The Two-Part System: Keys vs. Tokens

Instead of using one static key for all requests (which is a security risk), SignStack uses a more secure two-part system, similar to platforms like Stripe:

1. API Key (Long-Lived Secret):

  • What it is: A unique, secret credential you mint in Studio (Settings → API Keys), scoped to a specific namespace (which is itself either live or test — see Namespaces — Test vs. Live Mode). It carries a set of Scopes that define which actions it can authorize.
  • Its Job: It acts like your master key or password. Its only purpose is to securely authenticate with SignStack's /auth/token endpoint to obtain a temporary Access Token. It should never be sent with regular API calls.
  • Security: Keep your API Keys absolutely secret and secure on your backend server. Never expose them in frontend code.

2. JWT Access Token (Short-Lived Credential):

  • What it is: A standard JSON Web Token (JWT) that SignStack issues after you successfully authenticate with your API Key.
  • Its Job: It acts like a temporary session token or keycard. This is the token you include in the Authorization: Bearer <token> header for all standard API calls (like creating workflows or fetching blueprints).
  • Security: Access Tokens expire automatically (after 1 hour). If one is accidentally leaked, the security risk is significantly reduced because its validity window is very short.

Understanding Your API Key Structure

Your SignStack API Key follows this format: sk_ns_<mode>_<publicKey>_<secret>

  • sk_ns_: Fixed prefix marking this as a SignStack namespace-scoped secret key.
  • <mode>: Either live or test, mirroring the mode of the namespace this key belongs to (see Namespaces — Test vs. Live Mode). Surfaced in the prefix so you can tell at a glance whether a key in a config file points at production data.
  • <publicKey>: A unique, non-secret identifier (like a username) used by SignStack to quickly look up your key's record. It's safe to log this part for debugging.
  • <secret>: A long, cryptographically random, highly confidential string (like a password). This part must never be logged or exposed. SignStack hashes this part securely for verification.

Example: sk_ns_live_pk_a1b2c3d4_8f3e9c7d6b5a4f2e1d0c9b8a7f6e5d4c

The Authentication Flow

Here’s the standard process for authenticating API calls:

  1. Generate API Key: Create an API Key in Studio (Settings → API Keys). Choose the namespace it should be scoped to (the key inherits that namespace's mode) and assign appropriate Scopes. The full key string is shown only once at creation time — copy it immediately into your backend's secret management system. SignStack stores only a hash and cannot recover the plaintext later; if you lose it, revoke the key and mint a new one.

CLI shortcut: signstack auth login handles the key-to-token exchange automatically. You provide your API Key once and the CLI manages token refresh.

  1. Exchange Key for Token: Before making regular API calls (or whenever your previous token expires), your backend server makes a request to SignStack's token endpoint:
  • Endpoint: POST /v1/auth/token
  • Request Body:
{
  "grantType": "api_key",
  "apiKey": "sk_ns_live_..." // Your full, secret API Key
}
  • SignStack Logic: SignStack securely validates your API Key.
  • Response (200 OK): If valid, SignStack returns a short-lived JWT Access Token along with metadata about the authenticated subject:
{
  "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "tokenType": "Bearer",
  "expiresIn": 3600,
  "expiresAt": "2026-04-20T15:30:00.000Z",
  "scopes": ["blueprints:write", "workflows:read", "..."],
  "subject": {
    "type": "service_account",
    "id": "4d5e6f7a-8b9c-0d1e-2f3a-4b5c6d7e8f9a",
    "orgId": "f1e2d3c4-b5a6-4789-a012-345678901234",
    "namespaceKey": "acme-prod",
    "mode": "live"
  }
}
  1. Make API Calls with JWT: Use the obtained accessToken in the Authorization header for all other SignStack API calls. Resource endpoints are always namespace-scoped — see Namespaces for details.
curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
"https://api.signstack.ai/v1/orgs/{orgId}/namespaces/{namespaceKey}/blueprints"
  1. Handle Expiration: When an API call returns a 401 Unauthorized error, it likely means your accessToken has expired. Repeat Step 2 to get a fresh token and retry the original API call.

Security Benefits

This two-part system is the industry standard for secure APIs because:

  • Reduced Attack Window: Short-lived tokens significantly limit the time an attacker has if a credential is leaked.
  • Protection of Master Secret: The highly sensitive API Key is transmitted very rarely, minimizing its exposure.
  • Scoped Permissions: API Keys (and therefore the JWTs derived from them) carry only the Scopes you select at mint time, enforcing the principle of least privilege.
  • Environment isolation: A key is bound to a single namespace, so a key minted in a test namespace cannot touch a live namespace's data — accidental cross-environment writes are impossible.

Always handle your API Keys with the utmost security. Use the short-lived Access Tokens for all routine API interactions.

CLI Authentication

The signstack CLI handles the key/token exchange automatically:

# Interactive login (recommended)
signstack auth login

# Via environment variable
SIGNSTACK_API_KEY=sk_ns_live_xxx signstack auth login

# Pipe from stdin (CI/scripts)
echo "$SIGNSTACK_API_KEY" | signstack auth login --api-key-stdin

# Check current auth status
signstack auth whoami

# Remove stored credentials
signstack auth logout

Once authenticated, all CLI commands (push, preview, run) use the stored credentials with automatic token refresh.