All checks were successful
Build and Publish Docker Image / deploy (push) Successful in 2m44s
Introduce per-card accent colors to enhance the visual hierarchy of the documentation shortcut cards. This includes adding left borders, colored eyebrows, and matching hover glows using CSS variables. Additionally, this commit: - Adds color-coded tags (GET, POST, JSON, etc.) for API links. - Implements retro-themed styling for both the shortcut cards and tags to maintain consistency with the classic 16-color VGA palette. - Applies the new accent classes to the API page template.
515 lines
28 KiB
HTML
515 lines
28 KiB
HTML
{{define "api.html"}}{{template "base" .}}{{end}}
|
|
|
|
{{define "content"}}
|
|
<section class="api-docs" aria-labelledby="api-title" data-api-docs>
|
|
<aside class="api-sidebar">
|
|
<p class="kicker">Developer docs</p>
|
|
<h1 id="api-title" class="api-sidebar-title">Warpbox API</h1>
|
|
<nav class="api-nav" aria-label="Documentation sections">
|
|
<a class="api-nav-link" href="#home" data-doc-link>Home</a>
|
|
<a class="api-nav-link" href="#endpoints" data-doc-link>Endpoints</a>
|
|
<a class="api-nav-link" href="#cli" data-doc-link>CLI / Binary</a>
|
|
<a class="api-nav-link" href="#integrations" data-doc-link>Integrations</a>
|
|
<a class="api-nav-link" href="#examples" data-doc-link>Examples</a>
|
|
<a class="api-nav-link" href="#faq" data-doc-link>FAQ</a>
|
|
</nav>
|
|
<div class="api-sidebar-meta">
|
|
<a href="{{.Data.RequestSchemaURL}}">Request schema</a>
|
|
<a href="{{.Data.ResponseSchemaURL}}">Response schema</a>
|
|
</div>
|
|
</aside>
|
|
|
|
<div class="api-content">
|
|
|
|
<!-- ===================== HOME ===================== -->
|
|
<section id="home" class="doc-panel" data-doc-panel="home" tabindex="-1">
|
|
<header class="panel-head">
|
|
<p class="kicker">Get started</p>
|
|
<h2>Upload files anywhere, from anything</h2>
|
|
<p class="lead">Warpbox is a one endpoint upload API. Send a multipart file with <code>curl</code>, a script, ShareX, or the <code>warpbox</code> CLI and get back a shareable box link. Request JSON to also receive private manage and delete URLs.</p>
|
|
</header>
|
|
|
|
<div class="shortcut-grid">
|
|
<a class="shortcut-card accent-blue" href="#examples" data-doc-link>
|
|
<span class="shortcut-eyebrow">60-second start</span>
|
|
<span class="shortcut-title">Copy-paste examples</span>
|
|
<span class="shortcut-sub">curl, wget, HTTPie, Python & more</span>
|
|
</a>
|
|
<a class="shortcut-card accent-green" href="#cli" data-doc-link>
|
|
<span class="shortcut-eyebrow">Terminal</span>
|
|
<span class="shortcut-title">Install the CLI</span>
|
|
<span class="shortcut-sub">One command for macOS, Linux & Windows</span>
|
|
</a>
|
|
<a class="shortcut-card accent-violet" href="#endpoints" data-doc-link>
|
|
<span class="shortcut-eyebrow">Reference</span>
|
|
<span class="shortcut-title">All endpoints</span>
|
|
<span class="shortcut-sub">Payloads, responses & status codes</span>
|
|
</a>
|
|
<a class="shortcut-card accent-amber" href="#integrations" data-doc-link>
|
|
<span class="shortcut-eyebrow">Screenshots</span>
|
|
<span class="shortcut-title">ShareX integration</span>
|
|
<span class="shortcut-sub">Import once, upload as your account</span>
|
|
</a>
|
|
</div>
|
|
|
|
<div class="quickstart card">
|
|
<div class="card-content">
|
|
<h3>Your first upload</h3>
|
|
<p>No account required. This prints one plain box URL you can share immediately.</p>
|
|
<figure class="code-block">
|
|
<pre><code>curl -F file=@./report.pdf {{.Data.UploadURL}}</code></pre>
|
|
</figure>
|
|
<p class="muted-copy">Want file URLs, a manage link, and a delete link back? Add <code>-H 'Accept: application/json'</code>. See <a href="#responses" data-doc-link>the JSON response</a>.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<h3 class="section-label">Quick links</h3>
|
|
<div class="link-grid">
|
|
<a class="link-pill" href="#ep-upload" data-doc-link><span class="link-tag tag-post">POST</span> Upload endpoint</a>
|
|
<a class="link-pill" href="/static/api/warpbox.sh" download><span class="link-tag tag-get">GET</span> warpbox.sh (macOS/Linux)</a>
|
|
<a class="link-pill" href="/static/api/warpbox.ps1" download><span class="link-tag tag-get">GET</span> warpbox.ps1 (Windows)</a>
|
|
<a class="link-pill" href="{{.Data.ShareXDownloadURL}}" download><span class="link-tag tag-get">GET</span> ShareX .sxcu config</a>
|
|
<a class="link-pill" href="{{.Data.RequestSchemaURL}}"><span class="link-tag tag-json">JSON</span> Request schema</a>
|
|
<a class="link-pill" href="{{.Data.ResponseSchemaURL}}"><span class="link-tag tag-json">JSON</span> Response schema</a>
|
|
<a class="link-pill" href="/account/settings"><span class="link-tag tag-key">KEY</span> Create an API token</a>
|
|
<a class="link-pill" href="#faq" data-doc-link><span class="link-tag tag-help">?</span> FAQ & troubleshooting</a>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ===================== ENDPOINTS ===================== -->
|
|
<section id="endpoints" class="doc-panel" data-doc-panel="endpoints" tabindex="-1">
|
|
<header class="panel-head">
|
|
<p class="kicker">Reference</p>
|
|
<h2>Endpoints</h2>
|
|
<p class="lead">Base URL <code>{{.Data.BaseURL}}</code>. Authentication is optional: send <code>Authorization: Bearer <token></code> to upload as your account and use your account limits, or omit it to upload anonymously.</p>
|
|
</header>
|
|
|
|
<article id="ep-upload" class="endpoint card">
|
|
<div class="card-content">
|
|
<div class="endpoint-head">
|
|
<span class="method method-post">POST</span>
|
|
<code class="endpoint-path">/api/v1/upload</code>
|
|
</div>
|
|
<p>The core endpoint. Accepts a <code>multipart/form-data</code> body with one or more files. Returns a plain box URL by default, or the full JSON object when you send <code>Accept: application/json</code>.</p>
|
|
|
|
<h4>Request fields</h4>
|
|
<div class="field-grid">
|
|
<span><code>file</code></span><p>One or more files. Repeat the field for multiple files. Used by curl, browsers, and the CLI.</p>
|
|
<span><code>sharex</code></span><p>Alternative file field used by ShareX custom uploader configs. Same behaviour as <code>file</code>.</p>
|
|
<span><code>max_days</code></span><p>Optional. Days before the box expires. Defaults to 7.</p>
|
|
<span><code>expires_minutes</code></span><p>Optional. Lifetime in minutes. Takes precedence over <code>max_days</code> when > 0. Use it for expiries under a day (e.g. <code>60</code> = one hour).</p>
|
|
<span><code>max_downloads</code></span><p>Optional. Auto-expire the box after this many downloads.</p>
|
|
<span><code>password</code></span><p>Optional. Password required before viewing or downloading.</p>
|
|
<span><code>obfuscate_metadata</code></span><p>Optional <code>on</code>. Hides file names/counts until unlock (only meaningful with a password).</p>
|
|
</div>
|
|
|
|
<h4>Request headers</h4>
|
|
<div class="field-grid">
|
|
<span><code>Accept</code></span><p><code>application/json</code> to receive the JSON body; otherwise a single plain-text URL.</p>
|
|
<span><code>Authorization</code></span><p>Optional <code>Bearer <token></code>. Attributes the upload to your account.</p>
|
|
<span><code>X-Warpbox-Batch</code></span><p>Optional grouping key. Uploads sharing a value within {{.Data.ShareXGroupWindow}} land in the same box. See <a href="#integrations" data-doc-link>Integrations</a>.</p>
|
|
</div>
|
|
|
|
<h4>Example</h4>
|
|
<figure class="code-block">
|
|
<pre><code>curl -F file=@./report.pdf \
|
|
-F max_downloads=5 \
|
|
-F expires_minutes=1440 \
|
|
-H 'Accept: application/json' \
|
|
{{.Data.UploadURL}}</code></pre>
|
|
</figure>
|
|
</div>
|
|
</article>
|
|
|
|
<article id="responses" class="endpoint card">
|
|
<div class="card-content">
|
|
<h3>JSON response</h3>
|
|
<p>Returned when <code>Accept: application/json</code> is sent. The raw delete token appears <strong>only once</strong>, inside <code>manageUrl</code> and <code>deleteUrl</code>, so store them privately. Full schema: <a href="{{.Data.ResponseSchemaURL}}">upload-response.json</a>.</p>
|
|
<figure class="code-block">
|
|
<pre><code>{
|
|
"boxId": "abc123",
|
|
"boxUrl": "{{.Data.BaseURL}}/d/abc123",
|
|
"zipUrl": "{{.Data.BaseURL}}/d/abc123/zip",
|
|
"thumbnailUrl": "{{.Data.BaseURL}}/d/abc123/thumb/file123",
|
|
"manageUrl": "{{.Data.BaseURL}}/d/abc123/manage/private-token",
|
|
"deleteUrl": "{{.Data.BaseURL}}/d/abc123/manage/private-token/delete",
|
|
"expiresAt": "2026-06-05T12:00:00Z",
|
|
"files": [
|
|
{
|
|
"id": "file123",
|
|
"name": "report.pdf",
|
|
"size": "2.4 MiB",
|
|
"url": "{{.Data.BaseURL}}/d/abc123/f/file123",
|
|
"thumbnailUrl": "{{.Data.BaseURL}}/d/abc123/thumb/file123"
|
|
}
|
|
]
|
|
}</code></pre>
|
|
</figure>
|
|
<p class="muted-copy">On error the body is <code>{ "error": "message" }</code> with a non-2xx status. Common causes: <code>413</code> over the size limit, <code>429</code> rate limited or over your daily quota, <code>401</code> bad token.</p>
|
|
</div>
|
|
</article>
|
|
|
|
<article id="ep-resumable" class="endpoint card">
|
|
<div class="card-content">
|
|
<h3>Resumable uploads</h3>
|
|
<p>For large files. Browser uploads use this by default. Create a session with file metadata, <code>PUT</code> exact-sized chunks, then complete. Chunks are temporary and cleaned if the session expires. Send the same <code>Authorization</code> header on every request for authenticated sessions.</p>
|
|
<div class="endpoint-list">
|
|
<div><span class="method method-post">POST</span><code>/api/v1/uploads/resumable</code><em>Create a session</em></div>
|
|
<div><span class="method method-get">GET</span><code>/api/v1/uploads/resumable/{sessionID}</code><em>Session status</em></div>
|
|
<div><span class="method method-put">PUT</span><code>/api/v1/uploads/resumable/{sessionID}/files/{fileID}/chunks/{index}</code><em>Upload one chunk</em></div>
|
|
<div><span class="method method-post">POST</span><code>/api/v1/uploads/resumable/{sessionID}/complete</code><em>Finalize (returns the upload JSON)</em></div>
|
|
</div>
|
|
<figure class="code-block">
|
|
<pre><code># 1. Create a session.
|
|
curl -s {{.Data.BaseURL}}/api/v1/uploads/resumable \
|
|
-H 'Accept: application/json' \
|
|
-H 'Content-Type: application/json' \
|
|
-d '{"files":[{"name":"report.pdf","size":1048576,"contentType":"application/pdf"}],"expiresMinutes":1440}'
|
|
|
|
# 2. Upload each chunk using the returned sessionId, file id, and chunkSize.
|
|
dd if=./report.pdf bs=8388608 count=1 skip=0 2>/dev/null | \
|
|
curl -X PUT --data-binary @- \
|
|
{{.Data.BaseURL}}/api/v1/uploads/resumable/SESSION_ID/files/FILE_ID/chunks/0
|
|
|
|
# 3. Complete after all chunks are present. The response is the normal upload JSON.
|
|
curl -X POST -H 'Accept: application/json' \
|
|
{{.Data.BaseURL}}/api/v1/uploads/resumable/SESSION_ID/complete</code></pre>
|
|
</figure>
|
|
<p class="muted-copy">Incomplete chunks are stored under <code>data/tmp/uploads</code> before finalizing into the selected storage backend.</p>
|
|
</div>
|
|
</article>
|
|
|
|
<article id="ep-meta" class="endpoint card">
|
|
<div class="card-content">
|
|
<h3>Health & schemas</h3>
|
|
<div class="endpoint-list">
|
|
<div><span class="method method-get">GET</span><code>/health</code><em>Liveness check</em></div>
|
|
<div><span class="method method-get">GET</span><code>/api/v1/schemas/upload-request.json</code><em>Request JSON Schema</em></div>
|
|
<div><span class="method method-get">GET</span><code>/api/v1/schemas/upload-response.json</code><em>Response JSON Schema</em></div>
|
|
</div>
|
|
</div>
|
|
</article>
|
|
</section>
|
|
|
|
<!-- ===================== CLI / BINARY ===================== -->
|
|
<section id="cli" class="doc-panel" data-doc-panel="cli" tabindex="-1">
|
|
<header class="panel-head">
|
|
<p class="kicker">Terminal</p>
|
|
<h2>The <code>warpbox</code> CLI</h2>
|
|
<p class="lead">A tiny uploader script that wraps the API. It only needs <code>curl</code> (already on macOS, Linux, and Windows 10+). Point it at this instance once by setting <code>WARPBOX_HOST</code> to <code>{{.Data.BaseURL}}</code>, then upload from anywhere.</p>
|
|
</header>
|
|
|
|
<div class="download-row">
|
|
<div class="download-card">
|
|
<div class="download-os">macOS & Linux</div>
|
|
<p>POSIX shell script (<code>warpbox.sh</code>).</p>
|
|
<a class="button button-primary" href="/static/api/warpbox.sh" download>Download for macOS / Linux</a>
|
|
</div>
|
|
<div class="download-card">
|
|
<div class="download-os">Windows</div>
|
|
<p>PowerShell script (<code>warpbox.ps1</code>).</p>
|
|
<a class="button button-primary" href="/static/api/warpbox.ps1" download>Download for Windows</a>
|
|
</div>
|
|
</div>
|
|
|
|
<article id="cli-install" class="card">
|
|
<div class="card-content">
|
|
<h3>Install & add to PATH</h3>
|
|
|
|
<h4>macOS / Linux</h4>
|
|
<p>Download into a directory on your <code>PATH</code>, then make it executable. <code>~/.local/bin</code> is the recommended location.</p>
|
|
<figure class="code-block">
|
|
<pre><code>mkdir -p ~/.local/bin
|
|
curl -fsSL {{.Data.BaseURL}}/static/api/warpbox.sh -o ~/.local/bin/warpbox
|
|
chmod +x ~/.local/bin/warpbox
|
|
|
|
# Point it at this instance (add to ~/.profile or ~/.zshrc to keep it set)
|
|
echo 'export WARPBOX_HOST={{.Data.BaseURL}}' >> ~/.profile
|
|
|
|
# If 'warpbox: command not found', add the dir to PATH:
|
|
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.profile
|
|
# zsh users: use ~/.zshrc, then reload with: source ~/.profile</code></pre>
|
|
</figure>
|
|
<p class="muted-copy">Verify with <code>warpbox --help</code>. Prefer a system wide install? Drop it in <code>/usr/local/bin</code> with <code>sudo</code>.</p>
|
|
|
|
<h4>Windows (PowerShell)</h4>
|
|
<p>Save the script, then add a function to your PowerShell profile so <code>warpbox</code> works anywhere.</p>
|
|
<figure class="code-block">
|
|
<pre><code># Save it to your home folder
|
|
iwr {{.Data.BaseURL}}/static/api/warpbox.ps1 -OutFile $HOME\warpbox.ps1
|
|
|
|
# Point it at this instance, and add a 'warpbox' command (run once)
|
|
setx WARPBOX_HOST "{{.Data.BaseURL}}"
|
|
Add-Content $PROFILE 'function warpbox { & "$HOME\warpbox.ps1" @args }'
|
|
. $PROFILE # reload the profile</code></pre>
|
|
</figure>
|
|
<p class="muted-copy">If scripts are blocked, allow local scripts for your user: <code>Set-ExecutionPolicy -Scope CurrentUser RemoteSigned</code>.</p>
|
|
</div>
|
|
</article>
|
|
|
|
<article id="cli-usage" class="card">
|
|
<div class="card-content">
|
|
<h3>Usage</h3>
|
|
<p>A password, an expiry of two days, and a glob the shell expands for you:</p>
|
|
<figure class="code-block">
|
|
<pre><code>warpbox --password 123 --expiry 2d ./first_file.zip ./whatever.png ./all_*_photos.jpg</code></pre>
|
|
</figure>
|
|
<div class="field-grid">
|
|
<span><code>-p, --password</code></span><p>Require a password to open the box.</p>
|
|
<span><code>-e, --expiry</code></span><p>Lifetime: <code>30m</code>, <code>6h</code>, <code>2d</code>, <code>1w</code> (or bare minutes).</p>
|
|
<span><code>-n, --max-downloads</code></span><p>Expire after N downloads.</p>
|
|
<span><code>-o, --obfuscate</code></span><p>Hide names/counts until unlock (needs <code>--password</code>).</p>
|
|
<span><code>--json</code></span><p>Print the full JSON response instead of just the URL.</p>
|
|
<span><code>--host</code></span><p>Server to upload to. Defaults to your <code>WARPBOX_HOST</code>.</p>
|
|
</div>
|
|
<p class="muted-copy">Windows uses PowerShell flags: <code>warpbox -Password 123 -Expiry 2d .\file.zip</code>.</p>
|
|
</div>
|
|
</article>
|
|
|
|
<article id="cli-auth" class="card">
|
|
<div class="card-content">
|
|
<h3>Secure authentication</h3>
|
|
<p>To upload as your account (and use your account's size, daily, and retention limits), the CLI needs an API token. <strong>Set it in your environment</strong> so it never appears in your shell history or in the process list that any user on the machine can read:</p>
|
|
<figure class="code-block">
|
|
<pre><code># macOS / Linux (add to ~/.profile or ~/.zshrc to persist)
|
|
export WARPBOX_TOKEN=wbx_your_token
|
|
warpbox ./photo.png
|
|
|
|
# Windows (persist for your user)
|
|
setx WARPBOX_TOKEN "wbx_your_token"</code></pre>
|
|
</figure>
|
|
<p>For CI or shared machines, keep the token in a file with locked down permissions and point the CLI at it. This avoids putting the secret on the command line at all:</p>
|
|
<figure class="code-block">
|
|
<pre><code>printf '%s' "wbx_your_token" > ~/.warpbox-token
|
|
chmod 600 ~/.warpbox-token
|
|
warpbox --auth-file ~/.warpbox-token ./photo.png</code></pre>
|
|
</figure>
|
|
<p class="muted-copy"><code>--auth <token></code> exists for quick tests but is discouraged: it leaks into shell history and <code>ps</code>. Create or revoke tokens under <a href="/account/settings">Account, Access tokens</a>.</p>
|
|
</div>
|
|
</article>
|
|
</section>
|
|
|
|
<!-- ===================== INTEGRATIONS ===================== -->
|
|
<section id="integrations" class="doc-panel" data-doc-panel="integrations" tabindex="-1">
|
|
<header class="panel-head">
|
|
<p class="kicker">Integrations</p>
|
|
<h2>ShareX setup</h2>
|
|
<p class="lead">Import the uploader once, then optionally add your API key to upload as your account instead of as an anonymous guest.</p>
|
|
</header>
|
|
|
|
<article id="sharex" class="card">
|
|
<div class="card-content">
|
|
<h3>1. Import the uploader</h3>
|
|
<ol class="docs-steps">
|
|
<li>Download <a href="{{.Data.ShareXDownloadURL}}" download><code>warpbox-anonymous.sxcu</code></a>.</li>
|
|
<li>In ShareX: <code>Destinations → Custom uploader settings → Import → From file</code>, then pick the <code>.sxcu</code>.</li>
|
|
</ol>
|
|
|
|
<h3>2. Add your API key (optional, upload as your account)</h3>
|
|
<ol class="docs-steps">
|
|
<li>Create a personal access token under <a href="/account/settings">Account, Access tokens</a> and copy it.</li>
|
|
<li>In <code>Custom uploader settings</code>, select the Warpbox uploader and open the <code>Headers</code> section.</li>
|
|
<li>Add a header. Name <code>Authorization</code>, Value <code>Bearer <your token></code>.</li>
|
|
</ol>
|
|
<p class="muted-copy">Without that header, uploads stay anonymous. With it, they're attributed to your account and use your account's limits.</p>
|
|
|
|
<figure class="code-block">
|
|
<pre><code>{
|
|
"Version": "1.0.0",
|
|
"Name": "Warpbox (my account)",
|
|
"DestinationType": "ImageUploader, FileUploader, TextUploader",
|
|
"RequestMethod": "POST",
|
|
"RequestURL": "{{.Data.ShareXExampleURL}}",
|
|
"Headers": {
|
|
"Accept": "application/json",
|
|
"Authorization": "Bearer <span class="sxcu-highlight">YOUR_API_TOKEN</span>",
|
|
"X-Warpbox-Batch": "sharex"
|
|
},
|
|
"Body": "MultipartFormData",
|
|
"FileFormName": "{{.Data.ShareXFileFieldName}}",
|
|
"URL": "{json:boxUrl}",
|
|
"ThumbnailURL": "{json:thumbnailUrl}",
|
|
"DeletionURL": "{json:deleteUrl}",
|
|
"ErrorMessage": "{json:error}"
|
|
}</code></pre>
|
|
</figure>
|
|
|
|
<h3>Grouping multiple files into one box</h3>
|
|
<p>Grouping is <strong>opt in via the <code>X-Warpbox-Batch</code> request header</strong>. Without it, every file becomes its own box (the default). When the header is present, uploads sharing the same value (per account, or per IP for anonymous) within {{.Data.ShareXGroupWindow}} of each other are added to the <strong>same</strong> box, so a ShareX selection of several files produces one shareable link instead of one per file. The shipped config sets <code>X-Warpbox-Batch: sharex</code>; remove that header for one box per file.</p>
|
|
<p class="muted-copy">The response also exposes <code>{json:thumbnailUrl}</code> for ShareX previews, <code>{json:deleteUrl}</code> for the deletion URL, and <code>{json:error}</code> so ShareX surfaces messages like rate limiting.</p>
|
|
</div>
|
|
</article>
|
|
</section>
|
|
|
|
<!-- ===================== EXAMPLES ===================== -->
|
|
<section id="examples" class="doc-panel" data-doc-panel="examples" tabindex="-1">
|
|
<header class="panel-head">
|
|
<p class="kicker">Cookbook</p>
|
|
<h2>Examples</h2>
|
|
<p class="lead">Every snippet hits <code>POST {{.Data.UploadURL}}</code>. Add <code>-H 'Authorization: Bearer <token>'</code> to any of them to upload as your account.</p>
|
|
</header>
|
|
|
|
<article id="ex-curl" class="card">
|
|
<div class="card-content">
|
|
<h3>curl</h3>
|
|
<p>Plain text (one URL) for the shell; JSON for automation.</p>
|
|
<figure class="code-block">
|
|
<pre><code># Just the box URL
|
|
curl -F file=@./report.pdf {{.Data.UploadURL}}
|
|
|
|
# Full JSON with manage + delete URLs, password and 1-hour expiry
|
|
curl -F file=@./report.pdf \
|
|
-F password=hunter2 \
|
|
-F expires_minutes=60 \
|
|
-H 'Accept: application/json' \
|
|
{{.Data.UploadURL}}</code></pre>
|
|
</figure>
|
|
</div>
|
|
</article>
|
|
|
|
<article id="ex-wget" class="card">
|
|
<div class="card-content">
|
|
<h3>wget</h3>
|
|
<p>The endpoint needs a real <code>multipart/form-data</code> body, which <code>wget</code> can't assemble on its own, so build the body by hand and post it. It also shows the wire format:</p>
|
|
<figure class="code-block">
|
|
<pre><code>B=----warpbox$$
|
|
{ printf -- '--%s\r\nContent-Disposition: form-data; name="file"; filename="report.pdf"\r\nContent-Type: application/octet-stream\r\n\r\n' "$B"
|
|
cat ./report.pdf
|
|
printf -- '\r\n--%s--\r\n' "$B"; } > /tmp/wb.body
|
|
|
|
wget --quiet --output-document=- \
|
|
--header="Content-Type: multipart/form-data; boundary=$B" \
|
|
--header="Accept: application/json" \
|
|
--post-file=/tmp/wb.body \
|
|
{{.Data.UploadURL}}</code></pre>
|
|
</figure>
|
|
<p class="muted-copy">Add more form fields (<code>password</code>, <code>expires_minutes</code>, …) by repeating the <code>--%s … Content-Disposition: form-data; name="…"</code> block before the closing boundary. If this feels fiddly, <code>curl</code> or the CLI build the body for you.</p>
|
|
</div>
|
|
</article>
|
|
|
|
<article id="ex-httpie" class="card">
|
|
<div class="card-content">
|
|
<h3>HTTPie</h3>
|
|
<p>Multipart with form fields:</p>
|
|
<figure class="code-block">
|
|
<pre><code>http --multipart POST {{.Data.UploadURL}} \
|
|
Accept:application/json \
|
|
file@./report.pdf \
|
|
max_downloads=3 \
|
|
expires_minutes=1440</code></pre>
|
|
</figure>
|
|
</div>
|
|
</article>
|
|
|
|
<article id="ex-python" class="card">
|
|
<div class="card-content">
|
|
<h3>Python (requests)</h3>
|
|
<figure class="code-block">
|
|
<pre><code>import requests
|
|
|
|
with open("report.pdf", "rb") as f:
|
|
r = requests.post(
|
|
"{{.Data.UploadURL}}",
|
|
headers={"Accept": "application/json"}, # add "Authorization": "Bearer <token>"
|
|
files={"file": f},
|
|
data={"expires_minutes": 1440, "max_downloads": 5},
|
|
)
|
|
r.raise_for_status()
|
|
print(r.json()["boxUrl"])</code></pre>
|
|
</figure>
|
|
</div>
|
|
</article>
|
|
|
|
<article id="ex-node" class="card">
|
|
<div class="card-content">
|
|
<h3>Node.js (fetch)</h3>
|
|
<figure class="code-block">
|
|
<pre><code>import { readFile } from "node:fs/promises";
|
|
|
|
const form = new FormData();
|
|
form.set("file", new Blob([await readFile("report.pdf")]), "report.pdf");
|
|
form.set("expires_minutes", "1440");
|
|
|
|
const res = await fetch("{{.Data.UploadURL}}", {
|
|
method: "POST",
|
|
headers: { Accept: "application/json" }, // add Authorization: "Bearer <token>"
|
|
body: form,
|
|
});
|
|
const box = await res.json();
|
|
console.log(box.boxUrl);</code></pre>
|
|
</figure>
|
|
</div>
|
|
</article>
|
|
|
|
<article id="ex-ps" class="card">
|
|
<div class="card-content">
|
|
<h3>PowerShell</h3>
|
|
<p>PowerShell 7+ has native multipart with <code>-Form</code>:</p>
|
|
<figure class="code-block">
|
|
<pre><code>$resp = Invoke-RestMethod -Uri "{{.Data.UploadURL}}" -Method Post -Headers @{ Accept = "application/json" } -Form @{
|
|
file = Get-Item ".\report.pdf"
|
|
expires_minutes = 1440
|
|
}
|
|
$resp.boxUrl</code></pre>
|
|
</figure>
|
|
<p class="muted-copy">On Windows PowerShell 5.1, use the bundled <code>curl.exe</code> (the same approach the <a href="#cli" data-doc-link>CLI</a> takes) or the <code>warpbox.ps1</code> script.</p>
|
|
</div>
|
|
</article>
|
|
</section>
|
|
|
|
<!-- ===================== FAQ ===================== -->
|
|
<section id="faq" class="doc-panel" data-doc-panel="faq" tabindex="-1">
|
|
<header class="panel-head">
|
|
<p class="kicker">Help</p>
|
|
<h2>FAQ & troubleshooting</h2>
|
|
<p class="lead">Quick answers, each linking back to the relevant part of the docs.</p>
|
|
</header>
|
|
|
|
<div class="faq-list">
|
|
<details class="faq-item">
|
|
<summary>Do I need an account or API key?</summary>
|
|
<p>No. Anonymous uploads work without one, see the <a href="#home" data-doc-link>quickstart</a>. Add a token only to upload as your account and use your account's limits; set one up under <a href="/account/settings">Account, Access tokens</a> and pass it as described in <a href="#cli-auth" data-doc-link>CLI authentication</a>.</p>
|
|
</details>
|
|
<details class="faq-item">
|
|
<summary>How do I send a password, expiry, or download limit?</summary>
|
|
<p>They're multipart form fields on the upload endpoint: <code>password</code>, <code>expires_minutes</code> (or <code>max_days</code>), and <code>max_downloads</code>. See the full list under <a href="#ep-upload" data-doc-link>Endpoints, request fields</a>, or use the CLI flags in <a href="#cli-usage" data-doc-link>CLI usage</a>.</p>
|
|
</details>
|
|
<details class="faq-item">
|
|
<summary>How do I get file URLs and a delete link back?</summary>
|
|
<p>Send <code>Accept: application/json</code>. The response includes <code>boxUrl</code>, per-file <code>url</code>s, and the private <code>manageUrl</code>/<code>deleteUrl</code> (shown only once). See <a href="#responses" data-doc-link>the JSON response</a>.</p>
|
|
</details>
|
|
<details class="faq-item">
|
|
<summary>How do I upload one big file reliably?</summary>
|
|
<p>Use the <a href="#ep-resumable" data-doc-link>resumable endpoints</a>: create a session, PUT chunks, then complete. Interrupted uploads can resume from the last chunk.</p>
|
|
</details>
|
|
<details class="faq-item">
|
|
<summary>Can I upload several files into one shareable link?</summary>
|
|
<p>Yes. Send the <code>X-Warpbox-Batch</code> header with a shared value within {{.Data.ShareXGroupWindow}}. Details in <a href="#integrations" data-doc-link>Integrations, grouping</a>.</p>
|
|
</details>
|
|
<details class="faq-item">
|
|
<summary>Where's the keep-it-secret way to store my token?</summary>
|
|
<p>Use the <code>WARPBOX_TOKEN</code> environment variable or <code>--auth-file</code>, not <code>--auth</code> on the command line. Full guidance in <a href="#cli-auth" data-doc-link>CLI authentication</a>.</p>
|
|
</details>
|
|
<details class="faq-item">
|
|
<summary>My upload returns an error, what do the codes mean?</summary>
|
|
<p>Errors come back as <code>{ "error": "message" }</code> with a non-2xx status: <code>413</code> too large, <code>429</code> rate limited / over quota, <code>401</code> invalid token. See <a href="#responses" data-doc-link>error responses</a>.</p>
|
|
</details>
|
|
<details class="faq-item">
|
|
<summary>How do I use Warpbox from ShareX?</summary>
|
|
<p>Import the <code>.sxcu</code> and (optionally) add your token header. Step by step with the config in <a href="#integrations" data-doc-link>Integrations, ShareX setup</a>.</p>
|
|
</details>
|
|
<details class="faq-item">
|
|
<summary><code>warpbox: command not found</code> after install?</summary>
|
|
<p>The install directory isn't on your <code>PATH</code>. Fix it per your platform in <a href="#cli-install" data-doc-link>Install & add to PATH</a>.</p>
|
|
</details>
|
|
<details class="faq-item">
|
|
<summary>Is there a machine-readable schema?</summary>
|
|
<p>Yes: <a href="{{.Data.RequestSchemaURL}}">upload-request.json</a> and <a href="{{.Data.ResponseSchemaURL}}">upload-response.json</a> (JSON Schema 2020-12).</p>
|
|
</details>
|
|
</div>
|
|
</section>
|
|
|
|
</div>
|
|
</section>
|
|
{{end}}
|