creatorr.tech API.
JSON over HTTPS, bearer auth, the same API the app uses. Every server tool follows the same flow: presigned upload → enqueue job → poll status → presigned download.
# 1) Register / sign in to get a JWT.
curl -s -X POST https://api.creatorr.tech/v1/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"you@example.com","password":"********"}' \
| jq -r '.data.token' > token.txt
# 2) Mint a presigned upload URL.
curl -s -X POST https://api.creatorr.tech/v1/files \
-H "Authorization: Bearer $(cat token.txt)" \
-H 'Content-Type: application/json' \
-d '{"name":"input.pdf","mime_type":"application/pdf","size_bytes":1234567}' \
> presigned.json
# 3) Upload bytes directly to R2. The API never proxies file content.
curl -s -X PUT \
"$(jq -r '.data.upload_url' presigned.json)" \
-H 'Content-Type: application/pdf' \
--data-binary @input.pdf
# 4) Enqueue a job.
curl -s -X POST https://api.creatorr.tech/v1/jobs \
-H "Authorization: Bearer $(cat token.txt)" \
-H 'Content-Type: application/json' \
-d '{"tool":"compress_heavy","input_file_id":"'$(jq -r '.data.file_id' presigned.json)'","params":{"quality":70}}'Request and response shape
Successful responses are wrapped in { data: ... }. Errors are wrapped in { error: { code, message, request_id } }.Treat code as the contract; message may change.
# Success
{ "data": { "id": "fil_01J...", "name": "input.pdf", ... } }
# Error
{ "error": { "code": "validation", "message": "size_bytes must be > 0", "request_id": "req_01J..." } }Bearer auth: Authorization: Bearer <jwt>. Tokens are session-bound; signing out from one device revokes the JWT everywhere. Idempotency: Idempotency-Key header on POST /v1/jobs.
Common errors
unauthorized— missing or rejected token.invalid_credentials— wrong email or password.email_taken— email already registered.validation— request body failed validation.too_large— file exceeds the 10GB upload cap.unknown_tool— server tool slug not recognized.not_found— file or job missing or not yours.
Auth
Create a user account.
- emailstring
- passwordstring ≥ 8
- namestring (optional)
201: { token, expires_at, user }Sign in with email and password.
- emailstring
- passwordstring
200: { token, expires_at, user }
401: { error: { code: "invalid_credentials" } }Revoke the current session.
204
Return the current user.
200: { id, email, name, plan }Files
Mint a presigned upload URL for direct-to-R2 PUT.
- namestring
- mime_typestring
- size_bytesinteger (≤ 10GB)
201: { file_id, upload_url, expires_at, method, headers }Return file metadata + a presigned GET URL.
200: { id, name, size_bytes, mime_type, storage_tier, expires_at, created_at, download_url }Soft-delete a file.
204
Jobs
Enqueue a server-side tool against an uploaded file.
- tool"compress_heavy" | "office_to_pdf" | "ocr"
- input_file_idstring (from POST /v1/files)
- paramsobject (tool-specific)
201: { id, tool, status, progress, input_file_id, params }Poll job status until terminal (succeeded | failed | canceled).
200: { id, tool, status, progress, output_file_id?, error_code?, error_message? }Billing
Stripe Checkout session for a Pro subscription.
- cycle"monthly" | "yearly"
200: { url }Stripe Customer Portal session for an existing subscriber.
200: { url }Stripe webhook receiver. Verifies signature; updates user plan.
200: { received: true }Public API status
The endpoints above are real and stable, but bearer tokens are issued per-user via login — there's no public API key flow yet. Webhooks (other than Stripe billing) are not exposed. Public API keys, signed customer webhooks, and per-key rate limits land with the developer platform release.
If you want early access, drop a line.