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.
Authentication Flow
Section titled “Authentication Flow”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 │ │────────────────────────────────────►│Creating a Token
Section titled “Creating a Token”-
Backend call to the Allfeat API
Section titled “Backend call to the Allfeat API”backend/routes/ats-token.ts app.post('/api/ats-token', async (req, res) => {// Authenticate the user on YOUR side firstconst 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 });});Terminal window curl -X POST https://ats.api.allfeat.org/v1/sessions \-H "Content-Type: application/json" \-H "Origin: https://yoursite.com" \-d '{"secret_key": "csk_your_secret_key","action_type": "register","allowed_network": "testnet"}'Response:
{"token": "eyJhbGciOi...","expires_in": 300} -
Pass the token to the widget
Section titled “Pass the token to the widget”widget.setToken(token);
Session Parameters
Section titled “Session Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
secret_key | string | Yes | Your organization’s secret key (csk_...) |
action_type | string | Yes | "register", "update_version", or "access" |
allowed_network | string | Yes | "testnet" or "mainnet" |
allowed_ats_id | number | No | Restricts the token to a specific ATS work ID |
Required Headers
Section titled “Required Headers”| Header | Description |
|---|---|
Content-Type | application/json |
Origin | Must match one of the allowed domains configured for your organization in the Allfeat Dashboard. |
Action Types
Section titled “Action Types”| Action | Usage | Description |
|---|---|---|
register | mode="register" | Create a new ATS work |
update_version | mode="update" | Register a new version of an existing work |
access | mode="access" | Consult an existing work’s details |
One-Time-Use Tokens
Section titled “One-Time-Use Tokens”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.
Automatic Token Renewal
Section titled “Automatic Token Renewal”The JWT token expires after ~5 minutes. When the widget detects a 401 response, it:
- Pauses the current operation
- Emits the
allfeat:token-expiredevent with apendingActionfield - Waits for a new token via
setToken()(timeout: 60 seconds) - 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);});Domain Allowlist
Section titled “Domain Allowlist”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.
Credit Balance Check
Section titled “Credit Balance Check”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.
Security Best Practices
Section titled “Security Best Practices”- Never expose your
secret_keyon the client side - Always create tokens from your backend
- Verify the user’s identity on your backend before issuing a token
- Restrict
action_typeto the minimum required for the operation - Restrict
allowed_networkto 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_idwhen possible to limit the token’s scope to a specific work