# Storage · upload

`POST /v1/storage/objects` — Upload a file to the eroq Store and get a CDN URL back.

- Base URL: https://eroq.ai/v1
- Auth: `Authorization: Bearer eroq_sk_…` (create keys at https://eroq.ai/dashboard/keys)
- Credits: 2 per started 10MB, one-time

NSFW-friendly object storage over a global CDN — the missing half of every adult product's stack. Mainstream buckets and CDNs terminate accounts over adult media; the Store is governed by the same acceptable-use policy as the models, so what the API generates, the Store can host.

Send `multipart/form-data` with a `file` part (up to 100MB) and an optional `name`. The response carries the public CDN URL immediately — pair it with image or video generation to persist outputs in one extra call.

Pricing is a one-time 2 credits per started 10MB: storage stays as long as your account lives, serving included within fair use (sustained multi-TB egress on a single object moves to metered, with notice).

## Request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `file` | file | yes | The file to store (any type, up to 100MB). |
| `name` | string | no | Filename hint kept in the URL (sanitized). |

## Example request

```bash
curl https://eroq.ai/v1/storage/objects \
  -H "Authorization: Bearer $EROQ_API_KEY" \
  -F name=poster.webp \
  -F file=@poster.webp
```

```javascript
import { readFile } from 'node:fs/promises'

const form = new FormData()
form.append('name', 'poster.webp')
form.append('file', new Blob([await readFile('poster.webp')]), 'poster.webp')

const res = await fetch('https://eroq.ai/v1/storage/objects', {
  method: 'POST',
  headers: { Authorization: `Bearer ${process.env.EROQ_API_KEY}` },
  body: form,
})
console.log(await res.json())  // → { url: "https://store.eroq.ai/…" }
```

```python
import os, requests

res = requests.post(
    "https://eroq.ai/v1/storage/objects",
    headers={"Authorization": f"Bearer {os.environ['EROQ_API_KEY']}"},
    data={"name": "poster.webp"},
    files={"file": open("poster.webp", "rb")},
)
print(res.json())  # -> { "url": "https://store.eroq.ai/..." }
```

```go
package main

import (
	"bytes"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"os"
)

func main() {
	file, _ := os.Open("poster.webp")
	defer file.Close()

	var buf bytes.Buffer
	form := multipart.NewWriter(&buf)
	form.WriteField("name", "poster.webp")
	part, _ := form.CreateFormFile("file", "poster.webp")
	io.Copy(part, file)
	form.Close()

	req, _ := http.NewRequest("POST", "https://eroq.ai/v1/storage/objects", &buf)
	req.Header.Set("Authorization", "Bearer "+os.Getenv("EROQ_API_KEY"))
	req.Header.Set("Content-Type", form.FormDataContentType())

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(string(out))
}
```

## Response


```json
{
  "id": "0b52…",
  "object": "storage.object",
  "url": "https://store.eroq.ai/acc_…/8c1f2-poster.webp",
  "bytes": 482133,
  "content_type": "image/webp",
  "usage": { "credits_spent": 2, "credits_remaining": 880 }
}
```
---
Canonical: https://eroq.ai/docs/storage · Index for agents: https://eroq.ai/llms.txt · OpenAPI: https://eroq.ai/openapi.json
