Mobile Sync (iOS Shortcuts & Android Tasker)
Picora does not ship a native mobile app yet. Instead, v0.37.0 introduces a zero-app mobile sync path using the system automation tools already on your phone: iOS Shortcuts on iPhone/iPad, and HTTP Shortcuts or Tasker on Android. All three call the existing POST /v1/images API with your API key.
What you get
- Manual upload from the Share Sheet (iOS) or a launcher shortcut (Android)
- Automatic upload when a new photo is taken (iOS Personal Automation / Android Tasker)
- Public CDN URL copied to clipboard the moment upload completes
- Bandwidth-aware — videos > 50 MB are not recommended on cellular; the templates respect Wi-Fi-only by default
What you don’t get (limitations)
- iOS Personal Automation may require a manual tap on iOS 16 and below; iOS 17+ supports fully silent triggering.
- Bulk historical backfill (> 10,000 photos) is constrained by iOS Shortcut’s ~3-5 minute background time budget (~500 photos per batch). For full library import, use
@picora/photo-importerCLI (v0.56.0) instead.
Prerequisites
- A Picora account (sign up)
- An API Key with
image:writescope (generate one) - iOS 16+ for iPhone/iPad, Android 8+ for Android phones
iOS Shortcuts setup
Step 1 — Create the API Key
In Picora’s API Keys page, create a new key with the image:write scope only (least-privilege). Copy the sk_live_... value — you’ll see it only once.
Step 2 — Build the Shortcut
Open the Shortcuts app on iOS, tap + to create a new shortcut, then add these actions in order:
- Get Images from Input — receives the photo from the Share Sheet
- Get Contents of URL
- URL:
https://api.picora.me/v1/images - Method: POST
- Headers:
Authorization:Bearer sk_live_YOUR_KEYX-Picora-Client:shortcut-iosAccept-Language:Device Language(variable)
- Request Body: Form
file: the Image from step 1isPublic:true
- URL:
- Get Dictionary Value — key
data.urlfrom the JSON response - Copy to Clipboard — the URL
- Show Notification — “Uploaded to Picora:
<URL>”
In the shortcut’s settings, enable Show in Share Sheet and limit accepted input to Images.
Step 3 — Test it
In Photos, pick any image → tap the share icon → scroll down → tap your Picora Upload shortcut. Within seconds, you’ll see a notification and the URL is on your clipboard. Paste anywhere to verify.
Step 4 (optional) — Automate on photo capture
Open Shortcuts → Automation → +, choose Photo Taken, select Run Immediately (iOS 17+) or leave Ask Before Running on iOS 16. Pick your Picora Upload shortcut. New photos now sync automatically.
Step 5 (v0.55.1) — Upload videos (fire-and-forget)
POST /v1/videos returns 202 Accepted immediately with a videoId. Bunny.net transcodes asynchronously in the cloud — Shortcut does not need to poll. Create a separate “Picora Video Upload” shortcut:
- Get Media from Input — Type: Videos
- Get Contents of URL
- URL:
https://api.picora.me/v1/videos - Method: POST
- Headers:
Authorization:Bearer sk_live_xxx(must includevideo:writescope)X-Picora-Client:shortcut-ios-video
- Body: Form,
file=step 1 video,isPublic=true
- URL:
- Get Dictionary Value — path
data.id - Show Notification — “Picora video submitted for transcoding / ID:
<videoId>” - (Optional) Copy to Clipboard —
https://center.picora.me/videos/{videoId}
In the Shortcut’s Share Sheet settings, set input type to Videos (or combine with images in one Shortcut using an If branch on media type).
Step 6 (v0.55.1) — Historical photo backfill
iOS Shortcut’s built-in “Find Photos” action combined with server-side sha256 dedup lets you backfill old photos in batches. Re-running the same date window 100% hits dedup, so it never double-charges quota.
Create a new shortcut “Picora Historical Backfill”:
- Ask for Input — Type: Date, prompt “Backfill start date?”
- Ask for Input — Type: Date, prompt “Backfill end date?”
- Find Photos
- Filter: Date Created is between step 1 and step 2
- Media: Photos
- Limit: 500
- Repeat with Each (over step 3 results):
- 4a. Get Contents of URL (same as live upload, with header
X-Picora-Client: shortcut-ios-backfill) - 4b. Wait 0.5 seconds (avoid hitting the rate limit)
- 4a. Get Contents of URL (same as live upload, with header
- Show Notification — “Processed
<step 3 count>photos”
Usage tips:
- Pick a year-long window per batch, up to 500 photos
- Mid-batch timeout is harmless — re-run the same window, 100% hits dedup
- Full library (> 10,000 photos)? Use
@picora/photo-importermacOS CLI (v0.56.0) which has no background time budget
Android setup — HTTP Shortcuts (simpler)
HTTP Shortcuts is a free, open-source Android app. No root needed.
- Install HTTP Shortcuts from Play Store or F-Droid
- Create a new shortcut:
- Method:
POST - URL:
https://api.picora.me/v1/images - Headers: add
Authorization: Bearer sk_live_YOUR_KEYandX-Picora-Client: shortcut-android - Body type: Form data
- Form fields:
file(type: File) — select Pick file at executionisPublic(type: Text) — valuetrue
- Method:
- Under Scripting → On Success, paste:
const url = JSON.parse(response.body).data.url;copyToClipboard(url);showToast("Picora: " + url);
- Tap the shortcut from your launcher or add it to the Share Sheet via app settings.
Android setup — Tasker (auto-sync on photo)
Tasker is a paid app (~$3.49) but supports true background automation via the MediaStore content observer.
- Install Tasker + AutoTools (optional, for nicer notifications)
- Create a Profile:
- Event → File → File Modified
- Path:
Pictures/ - Set: include subdirectories
- Create a Task:
- HTTP Request action
- Method:
POST - URL:
https://api.picora.me/v1/images - Headers:
Authorization: Bearer sk_live_YOUR_KEYandX-Picora-Client: tasker - File parameter:
file→%evtprm2(path of new file) - Form:
isPublic=true
- Method:
- Variable Set —
%urlto%http_data.data.url(use the JSON Read action) - Notify — “Picora synced: %url”
- Set Clipboard —
%url
- HTTP Request action
- Under Profile settings, add State → Net → Wifi Connected if you want Wi-Fi-only.
Response headers worth knowing
| Header | Meaning |
|---|---|
X-Picora-Duplicate: true | The same photo (by sha256) is already in your library — Picora returned the existing record without re-uploading. Doesn’t count toward your quota. |
X-Picora-Idempotency-Replay: true | Your client sent Idempotency-Key and this is a cached response from a previous identical request. |
When testing automation, retrying with the same photo should produce X-Picora-Duplicate: true and the same URL.
Optional — batch hash precheck before bulk sync
If you’re writing a heavier automation that walks the entire camera roll (Shortcuts/Tasker won’t usually do this, but a power user might), call POST /v1/images/exists first with up to 200 SHA-256 hashes. The server returns which hashes are already in your library — skip those, upload the rest.
curl -X POST https://api.picora.me/v1/images/exists \ -H "Authorization: Bearer sk_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"hashes": ["aaaa...", "bbbb..."]}'Response:
{ "success": true, "data": { "existing": { "aaaa...": { "id": "abc123", "url": "https://media.picora.me/abc123.jpg" } }, "missing": ["bbbb..."] }}Troubleshooting
401 Unauthorized — API key is missing, malformed, or revoked. Regenerate at center.picora.me/api-keys.
403 Forbidden, code QUOTA_EXCEEDED — your storage or bandwidth quota is full. Check usage in Quota & Usage.
422 Validation error — usually wrong Content-Type or missing file field. Ensure the shortcut uses multipart/form-data (Form body), not raw JSON.
413 Payload Too Large — file > 10 MB on the free plan. Resize before uploading or upgrade your plan.
Shortcut runs but no URL appears — the response path is data.url, not just url. Double-check the JSON-parsing step.
What’s coming next
- Native iOS / Android apps (v0.38+, technology stack still under evaluation)
- TUS resumable upload for large videos (v0.37.0 backend already ships the API)
- Incremental sync via
GET /v1/sync/statecursor (v0.37.0 backend ready) — clients can pull deltas instead of full re-syncs
See Iteration v0.37.0 for the full backend changelog.