REST API Authentication
The REST API uses API keys as bearer tokens. One header, every request:
Authorization: Bearer YOUR_API_KEYAccept: application/jsoncurl --fail-with-body --silent --show-error \ -H "Authorization: Bearer $NUELINK_API_KEY" \ -H "Accept: application/json" \ https://app.nuelink.com/api/public/v1/meconst apiKey = process.env.NUELINK_API_KEY;
const response = await fetch('https://app.nuelink.com/api/public/v1/me', { headers: { Authorization: `Bearer ${apiKey}`, Accept: 'application/json', },});
if (!response.ok) { throw new Error(`HTTP ${response.status}: ${await response.text()}`);}
const data = await response.json();console.log(data);<?php
$apiKey = getenv('NUELINK_API_KEY');
$ch = curl_init('https://app.nuelink.com/api/public/v1/me');
curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => [ "Authorization: Bearer {$apiKey}", 'Accept: application/json', ], CURLOPT_RETURNTRANSFER => true,]);
$response = curl_exec($ch);$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);curl_close($ch);
if ($status >= 400) { throw new RuntimeException("HTTP {$status}: {$response}");}
echo $response;Generate a key
Section titled “Generate a key”- Open Settings → API.
- Click Generate API key.
- Copy it immediately. You can’t view it again after closing the screen.
- Store it in a secret manager, then reference it from there.
Check a key
Section titled “Check a key”GET /auth validates a key and returns the same profile as /me. A 200 means the key works; a 401 names the reason in errors.authorization. Both calls count only against the 60-per-minute route limit, not the 30-per-minute resource limit, so they’re cheap to run at startup. See Rate Limits.
The header, not the query string
Section titled “The header, not the query string”For compatibility with older clients, the API also accepts the key as an api_key query parameter. Don’t use it in anything new, and move existing clients to the Authorization header. Query strings leak into access logs, proxy logs, browser history, referrer headers, and screenshots, and unlike a header they’re often retained by infrastructure you don’t control. If a key has been sent in a URL, rotate it once the client is fixed.
The MCP server has its own, separately deprecated ?api_key= mode for clients that can’t do OAuth. See MCP Authentication.
Handling the key
Section titled “Handling the key”- Treat the key like a password. Anyone holding it acts with the key owner’s Nuelink permissions.
- Don’t call the API from browser code with a long-lived key. Call it from your backend.
- Use separate keys for separate environments or integrations when you want to revoke one without breaking the others. Staging and production should never share a key.
- Never commit a key to source control, including in a
.envthat isn’t gitignored. - Redact
Authorizationheaders from application and proxy logs. - Rotate immediately if a key turns up in a screenshot, a public issue, a log export, or a repository. Assume it’s compromised, not just exposed.
Revoking and rotating
Section titled “Revoking and rotating”Delete the old key in Settings → API, generate a replacement, and update the consuming service. Requests using a deleted key return 401.
There’s no automatic rotation in the alpha. If you need selective revocation, that’s what separate keys are for.
Team and multi-brand access
Section titled “Team and multi-brand access”A key inherits the brands and permissions of the Nuelink user who created it. It is scoped to the user, not to a workspace. If that user loses access to a team or a brand, the key loses it too.
Always list brands and resolve the one you want explicitly. Don’t assume the first result is correct, and don’t assume the set is stable across deploys.
Sensitive actions
Section titled “Sensitive actions”Deleting a post is a sensitive action. The API refuses DELETE /posts/{post_id} with 403 unless the account owner has enabled Allow AI to perform sensitive actions in Settings → API.
The setting is named for AI assistants, but it gates the endpoint itself: plain REST calls, MCP tools, and CLI commands are all refused until it’s on. Leave it off unless something you run needs to delete posts. To stop a post from going out, moving it back to DRAFT with PATCH works without it, and can be undone.
Authentication errors
Section titled “Authentication errors”| Status | Meaning | What to do |
|---|---|---|
401 | Key missing, invalid, or revoked | Check the header spelling, the key value, and whether the key still exists |
403 | Authenticated, but not permitted | Check the user’s team role, plan limits, and whether the action needs sensitive actions enabled |
404 | Resource absent, or invisible to this key | Re-resolve the brand, collection, or resource ID within the right brand |
The bodies you will actually receive, so you can match on them:
{ "status": "error", "message": "Token is required", "errors": { "authorization": "Token is required" }}{ "status": "error", "message": "Invalid Token", "errors": { "authorization": "Invalid Token" }}{ "status": "error", "message": "Token has expired", "errors": { "authorization": "Token has expired" }}A deleted key falls into one of these; the key is always authorization. Match on the HTTP status rather than the message text — the wording is not part of the contract.
A 404 on a resource you’re sure exists usually means the key belongs to a user without access to that brand, not that the resource is gone.
MCP uses something else
Section titled “MCP uses something else”The MCP server has its own OAuth-first flow and its own credential type. An OAuth access token is not a REST API key, and the two aren’t interchangeable. See MCP Authentication.