Authentication

Flux API delivers published content. Each Flux API instance can be public or require API keys. When authentication is enabled, every request must present a valid Flux API key using one of the supported methods. One exception has no toggle: write requests (POST/PUT and the MCP write tools) always require an authenticated key with the matching create/update grants — public APIs accept anonymous reads only.

Overview

  • Configuration – Toggle authentication per API when creating or updating it through the Management API.
  • Keys – Generate Flux API keys through the dashboard or Management API. Each key contains a Base64 public key and a private key that is shown only once.
  • Methods – Flux API supports Secure (signature-based, for server-side and SDK integrations that can sign each request) and Simple (static key, for MCP clients and any integration that can only send static headers).

When an API is marked as “authentication required”, unauthenticated requests return 401 with error_code authentication_required.


API Key Components

When you create a Flux API key you receive:

  • Name
    public_key
    Type
    string
    Description

    Base64 encoded compressed P-256 public key. Appears in the Authorization header.

  • Name
    secret_key
    Type
    string
    Description

    Base64 encoded private key in DER format. Used to sign data for Secure auth. The service never stores the full secret, so keep it safe.


Authentication Methods

  • Name
    Secure
    Description

    Signs each request using ECDSA P-256 + SHA256. Provides integrity, timestamp validation, and replay protection. Recommended for server-side and SDK integrations where code can compute a signature per request.

  • Name
    Simple
    Description

    Sends a static {public}:{private} key pair, like a bearer token. The recommended method for MCP clients and any integration that can only send static headers. Pair it with a dedicated, narrowly scoped Flux key.


Secure Authentication

Secure authentication verifies a signature built from the request path, body hash, and timestamp.

Because each signature covers the specific request body and timestamp, Secure signatures are per-request and cannot be pre-computed into a static header (for example, an MCP client config that only replays fixed headers). For those clients, use Simple authentication instead.

Required Headers

  • Name
    Authorization
    Type
    string
    Required
    required
    Description

    Secure <public_key>:<signature> where <signature> is Base64-encoded ECDSA output.

  • Name
    Date
    Type
    string
    Required
    required
    Description

    ISO 8601 UTC timestamp, e.g., 2025-01-12T08:15:30Z. Requests older than 15 minutes are rejected.

Data to Sign

  1. Compute the SHA-256 hash of the request body. Use the empty string when no body is present (e3b0c442…b855 in hex).
  2. Concatenate the pieces:
data_to_sign = "<request_path>|<body_hash>|<timestamp>"
  • request_path – The exact path sent to Flux API, including the API prefix and resource path (e.g., /blog-api/articles/_search). Do not include the protocol or host.
  • body_hash – Lowercase hex digest of the SHA-256 hash.
  • timestamp – Same value as the Date header.
  1. Sign data_to_sign with your private key using ECDSA over the P-256 curve and SHA-256. Encode the signature in Base64 and include it in the Authorization header.
import crypto from 'crypto';
import fetch from 'node-fetch';

const publicKey = process.env.FLUX_PUBLIC_KEY;
const privateKey = process.env.FLUX_PRIVATE_KEY; // Base64 DER
const uri = '/blog-api/articles/_search';
const body = JSON.stringify({
  where: {
    $: { all_of: [{ status__eq: 'published' }] }
  }
});

const bodyHash = crypto.createHash('sha256').update(body).digest('hex');
const timestamp = new Date().toISOString().replace(/\.\d{3}Z$/, 'Z');
const dataToSign = `${uri}|${bodyHash}|${timestamp}`;

const sign = crypto.createSign('SHA256');
sign.update(dataToSign);
const signature = sign.sign({
  key: Buffer.from(privateKey, 'base64'),
  format: 'der',
  type: 'pkcs8'
}).toString('base64');

const headers = {
  Authorization: `Secure ${publicKey}:${signature}`,
  Date: timestamp,
  'Content-Type': 'application/json'
};

const response = await fetch(`https://7c9h4pwu.fxns.io${uri}`, {
  method: 'POST',
  headers,
  body
});
console.log(await response.json());

Simple Authentication

Simple authentication sends a static public/private key pair in a single header, exactly like a bearer token:

Authorization: Simple <public_key>:<private_key>

The header never changes between requests, so it works in any client that can send a static Authorization header.

When to use it

Use Simple authentication for MCP clients (Claude Code, Claude Desktop, Cursor, the OpenAI Responses API), agent frameworks, and any tool that can only send static headers. These clients replay a fixed header on every call and cannot compute a per-request signature, so Secure authentication is not an option there.

Server-side code and SDK integrations that can sign each request should prefer Secure authentication, which adds integrity, timestamp validation, and replay protection.

Security note

Simple authentication does not sign requests: the same static credential is presented on every call. Mitigate this the way you would any long-lived API token:

  • Scope the key. Issue a dedicated Flux API key limited to only the APIs and collections the agent needs.
  • Always use TLS. Send the header only over HTTPS so the credential is never exposed in transit.
  • Rotate and revoke. Revoke a key immediately if it leaks, and rotate keys periodically.
  • Cap spend. Set a spend cap on the key so a compromised credential cannot run up unbounded usage.

Error Responses

When authentication fails, the Flux API returns 401 with JSON content similar to:

{
  "message": "Invalid signature",
  "error_code": "authentication_required",
  "detail": null
}

Common reasons:

  • Missing Authorization or Date header.
  • Incorrect path or body hash used during signature generation.
  • Timestamp outside the ±15 minute window.
  • Keys revoked or not authorized for the requested API prefix.

Verify all inputs before retrying to avoid throttling.

Was this page helpful?