Quickstart
Add phone and desktop uploads to a form in minutes: create a project, add a session endpoint, attach the widget.
How the pieces fit
- Your backend holds a secret API key (
sk_…) and exposes a session endpoint. It authenticates your own user, decides the file policy and calls CrossUpload. - The widget calls your session endpoint when the picker opens, receives short-lived session credentials, and uploads directly to private storage.
- Your form receives accepted file IDs in a hidden field. Your backend validates them before attaching them to a record.
pk_…) cannot create sessions.1. Create a project and key
- Create an account. A first project is created for you.
- In Dashboard → Projects, add your website’s origins (for example
https://www.example.com), allowed file types, size limit and default files per session. - In Dashboard → API keys, create a key for that project. It is shown once; store it in your server’s secret manager.
2. Add a session endpoint
Your endpoint calls POST /v1/sessions and returns the JSON response to the browser. Minimal example with curl:
curl -X POST https://app.crossupload.com/v1/sessions \
-H "Authorization: Bearer $CROSSUPLOAD_SECRET_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: application-42-attempt-1" \
-d '{"externalReference":"user:17:application:42","maxFiles":3,"origin":"https://www.example.com","locale":"en"}'
See Session endpoint (Rust/Axum) for a complete server example that authenticates users and applies server-owned limits.
3. Attach the widget
<form method="post" action="/applications">
<button type="button" id="upload">Upload a file</button>
<input type="hidden" id="attachments" name="attachment_ids" value="[]">
<button type="submit">Submit application</button>
</form>
<script src="https://app.crossupload.com/v1/widget.js"></script>
<script>
const uploader = CrossUpload.attach({
target: '#upload',
mode: 'picker',
sessionEndpoint: '/api/crossupload/session',
resultInput: '#attachments',
locale: 'en',
maxFiles: 3,
onComplete({ files }) { console.log('accepted', files); },
onError(error) { console.error(error.code, error.message); }
});
</script>
4. Validate on submit
When the form posts, attachment_ids contains a JSON array like [{"id":"file_…","sessionId":"ses_…", …}]. Do not trust it. For each ID call GET /v1/files/{id} with your secret key and check that status is ready, sessionId is a session you created for this user, and externalReference matches the record. Then store the file ID.
Need the file later? Call POST /v1/files/{id}/url for a fresh temporary URL. See Files, URLs & retention.
Try it
The live demo runs this exact flow against a server-owned demo project.
Something unclear or wrong? Email [email protected].