snapwonders-com Media Upload - TUS Resumable API
The [TUS](https://tus.io) resumable protocol at `/api/tus` — several requests per file: `POST` to create the upload, `PATCH` to send chunks, `HEAD` to query the offset and resume. More work to implement than **Media Upload - Direct** above, and worth it for three things: **files over 95 MB**, connections that drop (mobile, Tor, I2P), and per-chunk progress for a user watching an upload. This is what the snapWONDERS website and apps use. Set `Upload-Metadata: upload_uid ,step MQ==` for the primary file, or `step Mg==` for the cover media of a steganography hide. Authenticates with `X-Api-Key`, same as everything else. **No per-file size cap is applied at upload time** — size is checked when you start the job, against the total-size and file-count limits for your account tier (Pro allows more than free). So a large file will upload successfully and may still be rejected at `job_start`.
GET
/api/tus
TUS server information
#
POST
/api/tus
Initiate a new TUS upload
#
OPTIONS
/api/tus
Get TUS server configuration (capabilities, version, extensions)
#
GET
/api/tus/{tusId}
Get upload resource details
#
POST
/api/tus/{tusId}
Finalize a concatenated TUS upload (Creation With Upload)
#
DELETE
/api/tus/{tusId}
Cancel and delete a TUS upload resource
#
OPTIONS
/api/tus/{tusId}
Get TUS resource configuration
#
HEAD
/api/tus/{tusId}
Check the status (offset) of an in-progress TUS upload
#
PATCH
/api/tus/{tusId}
Upload a chunk of data for a specific TUS resource
#
Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/snapwonders-com:snapwonders-com-media-upload-tus-resumable-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: snapWONDERS API / MCP Media Upload - TUS Resumable API
description: 'The snapWONDERS API is available over **Clearnet**, **Tor** and **I2P** (dark web). All endpoints and this Swagger UI work identically on all three networks. ---
## Authentication
All endpoints **except `GET /api/status`, `OPTIONS /api/tus` and the no-auth MCP methods (`initialize`, `tools/list`, `status`, `*_get_started`)** require an API key, sent in the `X-Api-Key` request header (or as `Authorization: Bearer `):
```
X-Api-Key:
```
Obtain an API key from your **snapWONDERS account profile** once you have a registered account. Keys begin with `sw_` and are hashed server-side — store the raw key immediately after generation as it cannot be retrieved again. ---
## SDKs — skip the choreography
Everything below this section is the **raw HTTP contract**. You do not have to write it yourself. A full run means: create a session → upload each file → start a job → poll until it finishes → fetch the result URLs → download. Uploading is one `POST /api/upload` per file, so the tedious part is the polling and the plumbing rather than the transfer — unless your files are large enough to need the resumable protocol, which is genuinely fiddly. The **snapWONDERS SDKs** collapse all of it into one call. The first two examples do the **same thing** in each language — hide `secret.pdf` inside `cover.jpg` (Vaultify stego) — and the third shows forensic analysis. Each block is self-contained, so it runs as-is. ### Python — hide a file, then download the result
```python
from snapwonders import Client
client = Client(api_key="sw_...")
# The last path is the cover; everything before it is a secret. job = client.stego.hide(["secret.pdf", "cover.jpg"], password="Str0ng!Pass")
for result in job.results():
result.download("out/")
```
### JavaScript / TypeScript — the same hide, then download
```javascript
import { Client } from "@snapwonders/sdk";
const client = new Client("sw_...");
// The last path is the cover; everything before it is a secret. const job = await client.stego.hide(["secret.pdf", "cover.jpg"], { password: "Str0ng!Pass" });
for (const result of await job.results()) {
await result.download("out/");
}
```
### Python — forensic analysis, graded A–F
```python
from snapwonders import Client
client = Client(api_key="sw_...")
# Grade each file A–F and collect the overlays the analysis produced. job = client.analyse.run(["photo.jpg"], face_detection=True)
for item in job.results():
print(item.filename, item.grade, item.face_count)
for asset in item.assets: # ELA map, face overlay, …
asset.download("out/")
```
In JavaScript that is the same call — `await client.analyse.run(["photo.jpg"], { face_detection: true })` — with the result fields in camelCase (`item.faceCount`). Sessions, TUS chunking and resume, polling until the job finishes, retries on transient failures, and typed errors are all handled for you. `client.convert` (media conversion) follows the same shape: one call in, results out. | Language | Package | Install | Source |
|----------|---------|---------|--------|
| Python (3.10+) | `snapwonders` | `pip install snapwonders` | GitHub |
| JavaScript / TypeScript (Node 18+) | `@snapwonders/sdk` | `npm install @snapwonders/sdk` | GitHub |
| PHP (8.2+) | `snapwonders/sdk` | `composer require snapwonders/sdk` | GitHub |
| Go (1.21+) | — | `go get github.com/snapWONDERS/snapWONDERS-SDK-Go` | GitHub |
| Ruby, Java, C#, … | generated from this spec | see the Developers hub | — |
**Status:** All four are **live**. Python and JavaScript via `pip install snapwonders` / `npm install @snapwonders/sdk`; PHP via `composer require snapwonders/sdk` on Packagist; Go straight from GitHub with `go get`. All four clients are **open source on GitHub** (Python, JavaScript / TypeScript, PHP, Go). See the **Developers hub** for full quickstarts and the generation recipe for other languages. Prefer the raw API — or working in a language without a client? Everything the SDKs do is documented below; nothing is hidden from you.'
version: 1.0.0
servers:
- url: https://snapwonders.com
description: Clearnet / Web
- url: http://swonderstzr43aczpcwdoyc25vwxngyromja7pyb5sf26ap3v535sxqd.onion
description: Tor / Dark Web
- url: http://6ymp5jqysizmejdwaqiehcsgjoyb4s7sbgssquishk66drujomka.b32.i2p
description: I2P / Dark Web
security:
- ApiKey: []
tags:
- name: Media Upload - TUS Resumable
description: 'The TUS resumable protocol at `/api/tus` — several requests per file: `POST` to create the upload, `PATCH` to send chunks, `HEAD` to query the offset and resume. More work to implement than **Media Upload - Direct** above, and worth it for three things: **files over 95 MB**, connections that drop (mobile, Tor, I2P), and per-chunk progress for a user watching an upload. This is what the snapWONDERS website and apps use.
Set `Upload-Metadata: upload_uid ,step MQ==` for the primary file, or `step Mg==` for the cover media of a steganography hide. Authenticates with `X-Api-Key`, same as everything else.
**No per-file size cap is applied at upload time** — size is checked when you start the job, against the total-size and file-count limits for your account tier (Pro allows more than free). So a large file will upload successfully and may still be rejected at `job_start`.'
paths:
/api/tus:
get:
tags:
- Media Upload - TUS Resumable
summary: TUS server information
operationId: get_app_upload_tus_api
responses:
'200':
description: Success
security:
- ApiKey: []
post:
tags:
- Media Upload - TUS Resumable
summary: Initiate a new TUS upload
operationId: post_app_upload_tus_api
parameters:
- name: Upload-Length
in: header
description: Total byte size of the file to be uploaded
required: true
schema:
type: integer
- name: Upload-Metadata
in: header
description: Base64 encoded key-value pairs (e.g., "filename YWJjLmpwZw==,upload_uid MTIzNDU2")
required: true
schema:
type: string
- name: X-Api-Key
in: header
description: Your API key
required: true
schema:
type: string
responses:
'201':
description: Created — Check Location header for the upload resource URL
'401':
description: 'Not authenticated. `error` names the exact cause: `missing_api_key`, `malformed_api_key`, `invalid_api_key` (key unknown/revoked/expired), or — when the key itself is valid — `account_not_verified` / `account_inactive`. Access is additionally bounded by the session, which must already exist and belong to this key (422/403 otherwise).'
security:
- ApiKey: []
options:
tags:
- Media Upload - TUS Resumable
summary: Get TUS server configuration (capabilities, version, extensions)
operationId: options_app_upload_tus_api
responses:
'204':
description: Success — Check Tus-Version, Tus-Resumable, and Tus-Extension headers
security:
- ApiKey: []
/api/tus/{tusId}:
get:
tags:
- Media Upload - TUS Resumable
summary: Get upload resource details
operationId: get_app_upload_tus_api_chunk
parameters:
- name: tusId
in: path
description: The unique upload ID
required: true
schema:
type: string
- name: X-Api-Key
in: header
description: Your API key
required: true
schema:
type: string
responses:
'200':
description: Success — Returns metadata for the upload resource
security:
- ApiKey: []
post:
tags:
- Media Upload - TUS Resumable
summary: Finalize a concatenated TUS upload (Creation With Upload)
operationId: post_app_upload_tus_api_chunk
parameters:
- name: tusId
in: path
description: The unique upload ID
required: true
schema:
type: string
- name: Upload-Concat
in: header
description: Set to "final;<url1> <url2>" to merge partial uploads
required: false
schema:
type: string
- name: X-Api-Key
in: header
required: true
schema:
type: string
responses:
'201':
description: Concatenated upload created
'401':
description: Not authenticated — same five `error` codes as `POST /api/tus`.
security:
- ApiKey: []
delete:
tags:
- Media Upload - TUS Resumable
summary: Cancel and delete a TUS upload resource
operationId: delete_app_upload_tus_api_chunk
parameters:
- name: tusId
in: path
required: true
schema:
type: string
- name: X-Api-Key
in: header
required: true
schema:
type: string
responses:
'204':
description: Upload resource deleted
security:
- ApiKey: []
options:
tags:
- Media Upload - TUS Resumable
summary: Get TUS resource configuration
operationId: options_app_upload_tus_api_chunk
parameters:
- name: tusId
in: path
required: true
schema:
type: string
responses:
'204':
description: Success
security:
- ApiKey: []
head:
tags:
- Media Upload - TUS Resumable
summary: Check the status (offset) of an in-progress TUS upload
operationId: head_app_upload_tus_api_chunk
parameters:
- name: tusId
in: path
required: true
schema:
type: string
- name: X-Api-Key
in: header
required: true
schema:
type: string
responses:
'200':
description: Success — Check Upload-Offset header for current status
'404':
description: Upload resource not found
security:
- ApiKey: []
patch:
tags:
- Media Upload - TUS Resumable
summary: Upload a chunk of data for a specific TUS resource
operationId: patch_app_upload_tus_api_chunk
parameters:
- name: tusId
in: path
description: The unique upload ID obtained from the initiation POST
required: true
schema:
type: string
- name: Upload-Offset
in: header
description: The current byte offset of the file
required: true
schema:
type: integer
- name: Content-Type
in: header
required: true
schema:
type: string
default: application/offset+octet-stream
- name: X-Api-Key
in: header
required: true
schema:
type: string
responses:
'204':
description: Chunk uploaded successfully — Check Upload-Offset header for the new offset
'412':
description: Precondition Failed — Incorrect Upload-Offset
security:
- ApiKey: []
components:
securitySchemes:
ApiKey:
type: apiKey
description: 'API key generated on your snapWONDERS account profile page. Required everywhere except `GET /api/status`, `OPTIONS /api/tus` and the no-auth MCP methods. `Authorization: Bearer <key>` is also accepted.'
name: X-Api-Key
in: header