Skip to content

Authentication

The ATS Widget uses JWT session tokens to authenticate your organization’s actions with the Allfeat API. This ensures only requests authorized by your platform can register works — all under your organization’s Allfeat account.

User → Your Frontend → Your Backend → Allfeat API
│ │
│ POST /v1/sessions │
│ secret_key │
│──────────────────►│
│ │
│◄──────────────────│
│ { token } │
│ │
◄─────────────────│ │
token │
│ │
│ widget.setToken(token) │
│ │
│ Widget uses the token │
│ for all API requests │
│────────────────────────────────────►│
  1. backend/routes/ats-token.ts
    app.post('/api/ats-token', async (req, res) => {
    // Authenticate the user on YOUR side first
    const user = await getAuthenticatedUser(req);
    if (!user) return res.status(401).json({ error: 'Unauthorized' });
    const response = await fetch('https://ats.api.allfeat.org/v1/sessions', {
    method: 'POST',
    headers: {
    'Content-Type': 'application/json',
    'Origin': 'https://yoursite.com', // domain where the widget is embedded
    },
    body: JSON.stringify({
    secret_key: process.env.ALLFEAT_SECRET_KEY,
    action_type: 'register', // or 'update_version' or 'access'
    allowed_network: 'testnet', // or 'mainnet'
    // allowed_ats_id: 42, // optional, restricts to a specific work
    }),
    });
    if (!response.ok) {
    const error = await response.json();
    return res.status(response.status).json(error);
    }
    const { token, expires_in } = await response.json();
    res.json({ token });
    });
  2. widget.setToken(token);
ParameterTypeRequiredDescription
secret_keystringYesYour organization’s secret key (csk_...)
action_typestringYes"register", "update_version", or "access"
allowed_networkstringYes"testnet" or "mainnet"
allowed_ats_idnumberNoRestricts the token to a specific ATS work ID
HeaderDescription
Content-Typeapplication/json
OriginMust match one of the allowed domains configured for your organization in the Allfeat Dashboard.
ActionUsageDescription
registermode="register"Create a new ATS work
update_versionmode="update"Register a new version of an existing work
accessmode="access"Consult an existing work’s details

If you need to restart a flow from scratch (e.g., user abandons and retries), you must request a new token from your backend. The widget handles this automatically when it emits allfeat:token-expired.

The JWT token expires after ~5 minutes. When the widget detects a 401 response, it:

  1. Pauses the current operation
  2. Emits the allfeat:token-expired event with a pendingAction field
  3. Waits for a new token via setToken() (timeout: 60 seconds)
  4. Automatically retries the failed request
widget.addEventListener('allfeat:token-expired', async (e) => {
console.log('Token expired during:', e.detail.pendingAction);
// Call your backend for a new token
const { token } = await fetch('/api/ats-token', {
method: 'POST',
credentials: 'include',
}).then(r => r.json());
// The widget automatically retries the pending action
widget.setToken(token);
});

The Allfeat API validates the Origin header against your organization’s domain allowlist on every session creation. Configure your allowed domains in the Allfeat Dashboard.

Examples of domain patterns:

  • yoursite.com — exact match
  • *.yoursite.com — wildcard subdomain match

If the Origin header doesn’t match any allowed domain, the session creation will be rejected with a 403 Forbidden error.

Session creation also verifies that your organization has a sufficient credit balance to cover at least one registration. If the balance is too low, the API returns an error. Top up your credits in the Allfeat Dashboard.

  • Never expose your secret_key on the client side
  • Always create tokens from your backend
  • Verify the user’s identity on your backend before issuing a token
  • Restrict action_type to the minimum required for the operation
  • Restrict allowed_network to the network your application uses
  • For update mode, verify on your backend that the requesting user is the one who originally registered the work before issuing a token
  • Use allowed_ats_id when possible to limit the token’s scope to a specific work