Skip to content
All pages
  1. Overview
  2. Quick start
  3. Authentication
  4. API reference
    1. GET /media
    2. POST /media
    3. GET /media/{id}/preview
    4. GET /integrations/google/connect
    5. GET /integrations/google
    6. DELETE /integrations/google
    7. GET /integrations/google/folders
    8. POST /media/import
    9. GET /media/imports/{id}
    10. POST /renders
    11. GET /renders/{id}
    12. GET /renders/{id}/download
    13. GET /usage
  5. Code examples
  6. Error handling
  7. Rate limits & quotas
  8. Troubleshooting
  9. Changelog

Reference

POST

/api/v1/media

Requires the media:write scope.

Add a photo to your workspace library from raw bytes, and get back a media_id you can render immediately. This is what lets an integration run fully headless — no portal upload step.

Body fields

The shape is strict. Any field not in this table is 422 validation_failed rather than a silently ignored key — including url, storage_path and preview_url.

NameTypeRequiredNotes
filefile (multipart)yesThe image itself. JPEG, PNG, WebP or GIF; up to 15 MB. The format is detected from the bytes, not the filename.
labelstringnoOptional caption/label shown when browsing the library.
tagsstring[]noOptional. Repeat the field to send several.

Request

curl -s -X POST "https://omniscape.io/api/v1/media" \
  -H "Authorization: Bearer $OMNISCAPE_API_KEY" \
  -F "file=@photo.jpg" \
  -F "label=spring campaign"

Response

HTTP/1.1 201 Created

{
  "object": "media",
  "id": "c35c8330-5dd2-4170-b2b0-bae80ed7182f",
  "created_at": "2026-08-28T00:00:00.000Z",
  "label": "spring campaign",
  "tags": [],
  "width": null,
  "height": null,
  "mime_type": "image/jpeg",
  "file_size_bytes": 72267,
  "preview_url": "https://omniscape.io/api/v1/media/c35c8330-…/preview",
  "preview_expires_at": null
}

Notes

  • Send the image BYTES — the API takes no URL. That is deliberate: nothing here fetches a location you supply, which is what keeps the surface safe to expose.
  • The format is detected from the file itself, so a mislabeled Content-Type is rejected. JPEG, PNG, WebP and GIF are accepted (not SVG or video) — the same image formats the in-app media library takes.
  • The returned id is renderable straight away: hand it to POST /api/v1/renders. It also appears in GET /api/v1/media like any other library photo.
  • Uploads are rate-limited per key and count against your workspace storage — an over-budget upload is 402 quota_exceeded.
  • Needs a key with the media:write scope; a read-only key cannot upload.

Codes this call can return are on Error handling. If something is behaving unexpectedly, Troubleshooting is organised by symptom.