Skip to content

Signed Upload Tokens ​

Signed upload tokens are time-limited credentials designed for client-side uploads. They allow browsers and mobile apps to upload files directly to IPFS Ninja without exposing your API key.

A typical flow: your server generates a signed token using your API key, passes it to the client, and the client uses it to upload files. The token expires automatically after the specified duration.

Upload Tokens page for generating time-limited upload tokens

Step 1: Generate a Signed Token on Your Server ​

POST /upload/signed-url

Create a new signed upload token.

ParameterTypeRequiredDescription
namestringNoLabel for the token (e.g. "Mobile app uploads").
expiresInnumberYesToken lifetime in seconds.

Example request ​

bash
curl -X POST https://api.ipfs.ninja/upload/signed-url \
  -H "X-Api-Key: bws_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"name": "Mobile app", "expiresIn": 3600}'

Response 201 Created ​

json
{
  "token": "eyJ0b2tlbklkIjoiOWY4YzFhMmUtNGIzZC00ZTVmLThhOWItMWMyZDNlNGY1YTZiIiwi...",
  "tokenId": "9f8c1a2e-4b3d-4e5f-8a9b-1c2d3e4f5a6b",
  "tokenPrefix": "eyJ0b2tlbklk",
  "tokenName": "Mobile app",
  "expiresAt": 1711040400000,
  "createdAt": 1711036800000
}

WARNING

The full token is only returned once at creation. Store it securely or pass it directly to your client.

Step 2: List Your Signed Tokens ​

GET /signed-tokens

Returns all signed tokens for your account, including usage statistics.

Example request ​

bash
curl https://api.ipfs.ninja/signed-tokens \
  -H "X-Api-Key: bws_your_api_key_here"

Response 200 OK ​

json
[
  {
    "tokenId": "9f8c1a2e-4b3d-4e5f-8a9b-1c2d3e4f5a6b",
    "tokenPrefix": "eyJ0b2tlbklk",
    "tokenName": "Mobile app",
    "expiresAt": 1711040400000,
    "revoked": false,
    "useCount": 15,
    "lastUsedAt": 1711038600000,
    "createdAt": 1711036800000
  }
]

Step 3: Revoke a Signed Token ​

DELETE /signed-tokens/:tokenId

Immediately revoke a signed token. Any subsequent upload attempts using this token will be rejected.

ParameterTypeRequiredDescription
tokenIdstringYesThe token ID to revoke (e.g. "9f8c1a2e-4b3d-4e5f-8a9b-1c2d3e4f5a6b").

Example request ​

bash
curl -X DELETE https://api.ipfs.ninja/signed-tokens/9f8c1a2e-4b3d-4e5f-8a9b-1c2d3e4f5a6b \
  -H "X-Api-Key: bws_your_api_key_here"

Response 200 OK ​

json
{
  "success": true
}

Step 4: Use a Signed Token to Upload ​

To upload with a signed token, pass it via the Authorization header with the Signed scheme:

bash
curl -X POST https://api.ipfs.ninja/upload/new \
  -H "Authorization: Signed eyJ0b2tlbklkIjoiOWY4YzFhMmUtNGIzZC00ZTVmLThhOWItMWMyZDNlNGY1YTZiIiwi..." \
  -H "Content-Type: application/json" \
  -d '{"content": {"name": "example"}, "description": "Client upload"}'

The request body and response format are identical to a standard file upload.

Usage Tracking ​

Each time a signed token is used, the useCount is incremented and lastUsedAt is updated. You can monitor token activity via GET /signed-tokens.

Signed tokens are recorded with their prefix in the analytics API_KEY_PREFIX field. This means you can filter analytics by signed token prefix the same way you filter by API key prefix. See Analytics for details.

Example: Browser Upload ​

Generate a token on your server and use it in client-side JavaScript:

javascript
// Server-side: generate a token valid for 1 hour
const res = await fetch("https://api.ipfs.ninja/upload/signed-url", {
  method: "POST",
  headers: {
    "X-Api-Key": "bws_your_server_key",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({ name: "Web form", expiresIn: 3600 })
});
const { token } = await res.json();
// Pass `token` to the client

// Client-side: upload a file using the signed token
const file = document.getElementById("fileInput").files[0];
const reader = new FileReader();
reader.onload = async () => {
  const base64 = reader.result.split(",")[1];
  const uploadRes = await fetch("https://api.ipfs.ninja/upload/new", {
    method: "POST",
    headers: {
      "Authorization": `Signed ${token}`,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      content: base64,
      description: "User upload"
    })
  });
  const data = await uploadRes.json();
  console.log("Uploaded:", data.cid);
};
reader.readAsDataURL(file);