Przejdź do treści

Endpoints reference

Every route in the plugin integration API v1 — what it returns, when to use it, which permission it requires.

The canonical contract is the OpenAPI 3.1 specification (YAML) — it has the full schemas and every error response. This page summarises each route in a nutshell. If you are just getting started, read the main processes first.

Backwards-incompatible change (May 2026). POST /jobs and POST /jobs/batch no longer accept the old single-job body. You now send a session — one session_config (model, scenery, style, aspect ratio, suggestions) plus a list of subjects[], where each product expands into images_count generation jobs. See the migration note at the end of this page.

Identity

GET /me

Returns details about your installation and the merchant account: credit balance, plan, request limit, effective permissions, and the current list of sub-processors.

Permission: any valid key.

Jobs

POST /jobs

Order one photo session. Body: {job_type?, session_config, subjects[]} — one shared configuration for all products; the server creates images_count jobs per product. Response: {order_id, status, subjects: [{product_ref, job_ids: [...]}]}.

Tutorials: session from a ready packshot, packshot from a photo, session parameters.

Permission: plugin.jobs:create. Idempotency: supported (Idempotency-Key header, 24 h window).

Packshot approval requirement

A photo session (job_type omitted or photo_shoot) requires every product to have an approved packshot:

  • If you omit subjects[].packshot_asset_id, the server picks the latest approved packshot of the product named by product_ref.
  • If you pass packshot_asset_id explicitly, it must point to an approved packshot of the same product.
  • If a product has no approved packshot, the entire call returns 422 packshot_not_approved — nothing is created and no credits are charged.

How to get a product to an approved packshot — step by step in the "Packshot from a photo" tutorial.

Generating packshots

With job_type: "packshot" you order packshot candidates from a plain photo. Each product in the session must then have a packshot_asset_id (the input image) and auto_register_packshot: true (the generated candidate is added to the product's catalog). Candidates are not approved automatically — you approve the one you choose with POST /jobs/{id}/accept.

POST /jobs/batch

Order up to 100 sessions in one call. Body: {batches: [...]} — each entry is an independent session. Limits: 100 sessions and 5000 images total per call. The response is HTTP 207 with a per-session result. Tutorial: bulk sessions.

Permission: plugin.jobs:create. Idempotency: not available in v1 — retry failed sessions one at a time with POST /jobs using your own Idempotency-Key.

GET /jobs

Returns a list of your generation jobs, newest first. Parameters: status, created_after, created_before, limit (default 50, max 200), cursor (pagination).

Permission: plugin.jobs:read.

GET /jobs/{id}

Returns one job: its status, product details (product_label, product_ref, packshot_asset_id), the rating (voting, voting_at) and — for completed jobs — the list of outputs[] with download URLs for the images (valid for at least 7 days). Tutorial: receiving results.

Permission: plugin.jobs:read.

POST /jobs/{id}/accept

Records acceptance of a completed job. The effect depends on the job type:

  • packshot job — the generated packshot becomes the product's approved packshot and unblocks photo sessions (see the packshot approval requirement),
  • photo_shoot job — feedback only; it does not change credits, files, or the catalog.

Returns 204. 404 if the job belongs to another installation; 409 job_not_completed if the job has not finished. Re-rating overwrites the previous one.

Permission: plugin.jobs:read.

POST /jobs/{id}/reject

Records rejection of a completed job. Same contract as accept — including the catalog effect for packshot jobs: a rejected candidate will not be used in photo sessions.

Permission: plugin.jobs:read.

POST /jobs/{id}/refresh-url

Returns fresh download URLs for a completed job — use it when the previous ones have expired (after 7 days). 409 job_not_completed if the job is still running; 410 if the files have already been removed under the retention policy.

Permission: plugin.jobs:read.

DELETE /jobs/{id}

Cancels a job that has not started yet and releases the credit reservation. 409 job_not_cancelable if the job is already running or has finished.

Permission: plugin.jobs:cancel.

Sessions (orders)

GET /orders/{id}

Returns the whole session: its configuration (session_config), the per-product state (jobs_total, jobs_completed, jobs_failed), the generated images, and the credit summary (summary). Sessions of other installations return 404.

Permission: plugin.jobs:read.

POST /orders/{id}/clone

Creates a new session with the configuration and products of the source session. An empty body copies the products 1:1; a body with subjects[] is a full replacement of the list — only the listed products are cloned, each with a new images_count. Ratings do not carry over; credits are charged anew. Tutorial: repeat session.

Permission: plugin.jobs:create. Idempotency: required — the Idempotency-Key header is mandatory.

Files

POST /assets/upload

Returns a temporary URL for uploading a file (a product photo). Body: {mode: "presigned", filename, content_type, size_bytes} (max 50 MB). Send the bytes to the returned upload_url with PUT within 2 hours. You will reference the returned asset_id when you register an image or a packshot.

Permission: plugin.assets:upload.

Styles (presets)

GET /presets

Returns the list of styles available to the merchant — with a name, description, thumbnail, example gallery, credit cost, and guidance about input photos. Tutorial: session parameters.

Permission: plugin.catalog:read or plugin.jobs:read (older installations keep access).

Reference data

These endpoints let you build the session-parameter picker screen — see the parameters tutorial. All of them require the plugin.catalog:read permission.

GET /models

Returns the models available to the merchant — both their own account and the Qamera catalog. Each entry: id, name, thumbnail, source ('account' / 'marketplace'). Rejected and archived items are filtered out.

GET /sceneries

Sceneries — same shape and rules as /models.

GET /ai-models

Returns the AI models the merchant account may use (the list depends on the plan). Each entry: id ("provider/model" — goes into subjects[].ai_model), output_type, supported_aspect_ratios[], base_credit_cost. Every entry returned will be accepted by POST /jobs.

Cache privately only: Cache-Control: private, max-age=300, Vary: X-Api-Key.

GET /aspect-ratios

Returns the supported aspect ratios — exactly one has default: true. Cache freely: Cache-Control: public, max-age=3600.

GET /pricing

Returns the credit price list per (job_type, provider, model) — an entry with model: "*" is the provider's default price. Consistent with base_credit_cost from /ai-models. Caching: Cache-Control: public, max-age=300.

Product catalog

A persistent catalog of the merchant's products, their source images, and their packshots. You identify records with your own stable identifiers (external_ref) — these are what tie your shop to Qamera AI. Bulk endpoints accept up to 100 items per call. Records of other installations return 404.

POST /images

Registers source product images (uploaded earlier via /assets/upload). Creates the product automatically when product_ref is new and you provide product_metadata.display_name. Calling again with the same external_ref returns the existing row (status: "existing"). Tutorial: packshot from a photo.

Permission: plugin.catalog:write.

POST /packshots

Registers ready packshots. Packshots uploaded this way are approved automatically — they immediately satisfy the requirement for photo sessions. source_image_ref (optional) links the packshot to a source image. Tutorial: session from a ready packshot.

Permission: plugin.catalog:write.

GET /products

Returns a list of your products (cursor pagination): id, external_ref, display_name, sku, image_count, packshot_count. Deleted products are skipped by default.

Permission: plugin.catalog:read.

GET /products/{id_or_ref}

Returns one product with its embedded images and packshots (up to 100 each; the images_truncated / packshots_truncated flags signal that there are more). In the path you can pass a UUID or your own external_ref. Each embedded packshot also reports its rating (voting, voting_at) — the same fields as in GET /packshots.

Permission: plugin.catalog:read.

DELETE /products/{id_or_ref}

Deletes a product (softly — its images and packshots stay). You can later register the same external_ref again as a new product.

Permission: plugin.catalog:write.

GET /packshots

Returns a list of your packshots (cursor pagination). The product_ref parameter narrows it to one product. Each packshot includes its rating: voting (pending, accepted, or rejected) and voting_at (when the decision was made). A packshot with voting: "accepted" meets the packshot approval requirement — check here which packshot unblocks photo sessions for a product. Packshots registered via POST /packshots are accepted from the start.

Permission: plugin.catalog:read.

DELETE /packshots/{id_or_ref}

Removes a packshot entry from the catalog. The file itself stays — other records may reference it.

Permission: plugin.catalog:write.

Installation

POST /installations/{id}/rotate-hmac

Rotates the HMAC secret used to sign webhooks. The previous secret keeps working for another 48 hours, so notifications in flight are not lost. The new secret is in the response — we show it only once.

Permission: plugin.installations.manage.

Webhooks

POST /webhooks/{delivery_id}/replay

Re-sends a webhook notification — use it when your endpoint was down during the automatic retry window. Tutorial: receiving results.

Permission: plugin.webhooks:manage.

Migration from the previous v1 shape

The old POST /jobs body ({job_type, provider, model, unit_cost, settings}) and the old POST /jobs/batch body ({jobs: [...]}) are no longer supported and return 400 invalid_input.

Moving to the session shape:

  1. Wrap your existing single-job parameters into one subjects[] entry: {packshot_asset_id, product_label, product_ref, images_count, ai_model: "provider/model"}.
  2. Move the model/scenery/style/aspect-ratio up into session_config. The ai_model field replaces the old provider/model/unit_cost trio — cost is calculated server-side.
  3. In batch calls, change jobs to batches — each entry is one complete session.
  4. Webhook notifications now carry additional fields (packshot_asset_id, product_label, product_ref, voting, voting_at) — you can ignore them if you do not need them.