Upload file
Upload a single file. The file is added to IPFS and pinned in the cluster.
Scope required: files:write
Endpoint
| Method | POST |
| URL | https://api.pinarkive.com/api/v3/files |
| Content-Type | multipart/form-data |
Headers: Authorization: Bearer YOUR_API_KEY or X-API-Key: YOUR_API_KEY
Body: Form field file (required). Optional: cl (cluster id), timelock (ISO 8601, premium only).
Request
cURL
curl -X POST https://api.pinarkive.com/api/v3/files \
-H "X-API-Key: YOUR_API_KEY" \
-F "file=@image.png"With optional cluster and timelock (premium):
curl -X POST https://api.pinarkive.com/api/v3/files \
-H "X-API-Key: YOUR_API_KEY" \
-F "file=@document.pdf" \
-F "cl=cl0-global" \
-F "timelock=2026-12-31T23:59:59Z"JavaScript (fetch)
const form = new FormData();
form.append("file", file);
const response = await fetch("https://api.pinarkive.com/api/v3/files", {
method: "POST",
headers: {
"X-API-Key": process.env.PINARKIVE_API_KEY,
},
body: form,
});
const data = await response.json();JavaScript (axios)
const form = new FormData();
form.append("file", file);
const { data } = await axios.post(
"https://api.pinarkive.com/api/v3/files",
form,
{
headers: {
"X-API-Key": process.env.PINARKIVE_API_KEY,
},
}
);Python
import os
import requests
url = "https://api.pinarkive.com/api/v3/files"
headers = {"X-API-Key": os.environ["PINARKIVE_API_KEY"]}
files = {"file": open("image.png", "rb")}
data = {"cl": "cl0-global"} # optional
r = requests.post(url, headers=headers, files=files, data=data)
r.raise_for_status()
print(r.json())Go
package main
import (
"bytes"
"io"
"mime/multipart"
"net/http"
"os"
)
func main() {
url := "https://api.pinarkive.com/api/v3/files"
apiKey := os.Getenv("PINARKIVE_API_KEY")
var buf bytes.Buffer
w := multipart.NewWriter(&buf)
file, _ := os.Open("image.png")
defer file.Close()
part, _ := w.CreateFormFile("file", "image.png")
io.Copy(part, file)
w.WriteField("cl", "cl0-global")
w.Close()
req, _ := http.NewRequest("POST", url, &buf)
req.Header.Set("X-API-Key", apiKey)
req.Header.Set("Content-Type", w.FormDataContentType())
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
}PHP
<?php
$url = 'https://api.pinarkive.com/api/v3/files';
$apiKey = getenv('PINARKIVE_API_KEY');
$cfile = new CURLFile('image.png', 'image/png', 'image.png');
$post = ['file' => $cfile, 'cl' => 'cl0-global'];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-API-Key: ' . $apiKey]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);Response
Success (200 / 201)
{
"cid": "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
"clusterId": "cl0-global",
"expiresAt": "2026-12-31T23:59:59.000Z"
}| Field | Type | Description |
|---|---|---|
cid | string | IPFS content identifier |
clusterId | string | Cluster where the file was pinned |
expiresAt | string | null | Expiration (timelock), if set |
Error (4xx / 5xx)
{
"error": "Unauthorized",
"message": "Invalid or missing API key",
"code": "INVALID_API_KEY"
}Common codes: 401 (invalid/missing key), 403 (plan limit, timelock on free plan, or code: missing_scope, required), 413 (file too large), 429 (rate limit; use retryAfter / Retry-After). See Error handling.