ZumiLabs CloudSend

Send files from your browser
to anywhere. Securely.

CloudSend is the server-side piece that makes your browser tools smarter. Upload a screenshot from OmniCapt, a file from ZumiFiles, or any file from any web app — and send it directly to Jira, Slack, GitHub, Miro, Google Drive, S3, or Confluence. Your API keys stay on the server. The browser never sees them.

Self-hosted Node.js server API keys stay server-side 8 cloud targets
Screenshot needed
☁️
CloudSend Status Dashboard
The CloudSend status page at localhost:8081 showing configured targets (Jira, Slack, GitHub) with green "Configured" badges and others with amber "Not configured"
What to capture
Run CloudSend locally and open http://localhost:8081 in a browser
Configure at least Jira and Slack with real tokens so they show green "Configured" badges
Leave 1–2 targets unconfigured so the amber "Not configured" state is visible for contrast
Capture the full status page — dark theme, 1280px wide
8
Cloud Targets
3
Integration Styles
Zero
Client-side Secrets
Self
Hosted on Your Server
How it Works

A secure bridge between your browser tools and your cloud services.

Browser extensions and web apps can't safely hold API keys — they can be extracted. CloudSend moves those keys to a server you control, and exposes a single authenticated API your clients use instead.

The Architecture

Your secrets on your server. Your clients stay clean.

OmniCapt, ZumiFiles, or any web app sends a file to CloudSend with a JWT token. CloudSend verifies the token, looks up which cloud target you want, and delivers the file using the API credentials stored only on the server. The client never has access to Jira API tokens, Slack bot keys, or GitHub personal access tokens.

Client sends: file + JWT + destination ID
Server holds: all third-party API credentials
Server delivers: to Jira / Slack / GitHub / etc.
Client receives: success confirmation (or error)
Request flow
Browser / Extension
OmniCapt · ZumiFiles · any app
JWT + file + target ID
CloudSend Server
API keys live here only
native API calls with server credentials
Jira Slack GitHub Miro Drive S3
Supported Targets

Send to the tools your team already uses.

Each target has a full browse-and-upload flow: navigate the hierarchy (projects → issues, channels, boards) then send the file exactly where it needs to go.

Jira
Attach files to any issue
Confluence
Attach or embed on a page
Slack
Upload to any channel
GitHub
Commit asset + post comment
Miro
Grid layout on a board
Amazon S3
PUT to bucket / prefix
Google Drive
Upload to any folder
Contentful
Upload + publish as Asset
Screenshot needed
🎫
Browse-to-Upload Flow — Jira Example
The web component showing the target picker → Jira project browser → issue selector → file queue → upload confirmation
What to capture
Open the CloudSend web component demo at /demo/web-component.html with Jira configured
Navigate: select Jira → pick a project → pick an issue → drop in a file → hit Upload
Capture each step OR the component after a successful upload showing the green success state
Dark theme, 1280px wide
Three Ways to Integrate

Pick the integration style that fits your project.

All three approaches call the same REST API underneath — choose based on how much you want to build yourself.

01
Drop-in Web Component
Add the <zumilabs-cloudsend> element to any page. It renders a complete UI: target picker, browse tree, file queue, and upload button. Two lines of HTML. Works in any framework.
<script src="/web-component/index.global.js"></script> <zumilabs-cloudsend endpoint="http://your-server/api/v1" token="your-jwt"> </zumilabs-cloudsend>
02
TypeScript SDK
A headless typed wrapper for building custom UIs. Works in browsers, Node 18+, Chrome extension service workers, and Cloudflare Workers. No runtime dependencies.
import { CloudSendClient } from '@zumilabs/cloudsend-client'; const client = new CloudSendClient({ endpoint: 'http://your-server/api/v1', token: 'your-jwt', }); await client.upload.jira({ issueKey: 'KAN-11', files: [file], });
03
REST API
Call the HTTP API directly from any language. Browse a target's hierarchy to find the destination, then POST the file with multipart form data. Full OpenAPI spec included.
# Browse Jira for an issue curl -H "Authorization: Bearer $JWT" \ /api/v1/targets/jira/browse?parent_id=project:KAN # Upload to it curl -X POST \ -F "issue_key=KAN-11" \ -F "[email protected]" \ /api/v1/targets/jira/upload
Security Model

Your credentials never leave your server.

CloudSend's entire purpose is to keep secrets out of the browser. Here's exactly how.

🔑
Server-side credentials only
Jira API tokens, Slack bot keys, GitHub PATs, and all other third-party credentials are stored only as environment variables on your server. Browser clients never see them — not in responses, not in headers, not anywhere.
🪪
JWT authentication
Every request requires a signed JWT in the Authorization header. In production, CloudSend verifies the signature against your identity provider's JWKS endpoint (Auth0, Cognito, or any standards-compliant IdP). Invalid or expired tokens are rejected.
🏠
Self-hosted
CloudSend runs on infrastructure you control. ZumiLabs never has access to your files, your API keys, or your cloud services. Files pass through your server to your targets — nothing is routed through any ZumiLabs infrastructure.
🏢
Multi-tenant ready
JWTs carry a sub (user ID) and custom:tenant_id claim. CloudSend uses these for tenant-scoped file paths and routing — making it straightforward to deploy as shared infrastructure in a SaaS product where multiple teams use the same server with isolated storage.
Local development quick-start

From the ZumiLabs repository, you can have CloudSend running locally in under two minutes:

# From the repository root
cd apps/cloudsend
npm install
cp .env.example .env
# Edit .env — add only the target credentials you need
DEV_AUTH_BYPASS=tenant1:user1 node src/index.js
# → Server at http://localhost:8081 — open to see the status page
FAQ

Common questions.

Yes. CloudSend is a Node.js/Express server you run on your own infrastructure. This is by design — keeping your API credentials on a server you control is the core security model. You can run it locally during development, or on any Node.js-compatible host (VPS, container, cloud function) in production.

No. Configure only the targets you need by adding the relevant environment variables to your .env file. Unconfigured targets show an amber "Not configured" badge on the status page and return a clear error if called. Everything else works normally.

OmniCapt can send captures to CloudSend directly after taking a screenshot. In OmniCapt settings, you configure the CloudSend server URL and your JWT. After each capture, a "Send via CloudSend" panel appears in the popup — select the target and destination, hit send. OmniCapt hands the file to CloudSend; CloudSend delivers it.

Not currently. CloudSend is designed to be self-hosted so your credentials remain entirely within your infrastructure. If a managed option is something you'd find valuable, get in touch — we're interested in hearing what teams need.

Get CloudSend

The secure bridge between your browser tools and your cloud.

CloudSend is available to ZumiLabs customers. Get in touch to find out how to set it up for your team.