Session from a packshot

Step by step — from uploading a ready packshot to receiving the session images and rating the results.

What you'll achieve

The merchant already has a product packshot — a photo on a clean, neutral background. In this tutorial you'll upload that file, register it as a packshot (it gets approved automatically), order a photo session, and receive the finished images.

Prerequisites

  • A plugin installation API key (how to get one) with these permissions: plugin.assets:upload, plugin.catalog:write, plugin.jobs:create, plugin.jobs:read.
  • The packshot file (JPEG/PNG/WebP, up to 50 MB).

In the examples, replace mk_live_… with your own key. The base address is https://qamera.ai.

Flow

1. POST /assets/upload      → asset_id + a temporary upload URL
2. PUT <upload_url>         → send the file
3. POST /packshots          → register the packshot (approved immediately)
4. POST /jobs               → order a photo session
5. webhook / GET /jobs/{id} → receive the finished images
6. POST /jobs/{id}/accept   → (optional) rate the results

Steps

1. Get a temporary URL to upload the file

curl -X POST https://qamera.ai/api/v1/plugin/assets/upload \
  -H "X-Api-Key: mk_live_xxxxxxxx.yyyyyyyy" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "presigned",
    "filename": "kubek-packshot.jpg",
    "content_type": "image/jpeg",
    "size_bytes": 482310
  }'

Response (HTTP 201):

{
  "asset_id": "9a3b8f4c-2e7a-4c1b-8d0a-1f6c2e9b3d51",
  "upload_url": "https://…/sign/…",
  "expires_at": "2026-06-03T14:00:00.000Z"
}

Save asset_id — you'll use it in step 3. The upload_url is valid for 2 hours; if it expires, just request a new one.

2. Send the file

curl -X PUT "$UPLOAD_URL" \
  --upload-file kubek-packshot.jpg \
  -H "Content-Type: image/jpeg"

3. Register the packshot

Packshots you upload yourself are approved automatically — we assume that if you picked them, they're ready to use. If the product with the given product_ref doesn't exist in the catalog yet, provide product_metadata.display_name and it will be created.

curl -X POST https://qamera.ai/api/v1/plugin/packshots \
  -H "X-Api-Key: mk_live_xxxxxxxx.yyyyyyyy" \
  -H "Content-Type: application/json" \
  -d '{
    "packshots": [
      {
        "external_ref": "sklep1:packshot-42",
        "product_ref": "sklep1:produkt-7",
        "product_metadata": { "display_name": "Kubek ceramiczny 300 ml" },
        "asset_id": "9a3b8f4c-2e7a-4c1b-8d0a-1f6c2e9b3d51"
      }
    ]
  }'

Response (HTTP 200):

{
  "results": [
    {
      "external_ref": "sklep1:packshot-42",
      "product_id": "5e1f8a2c-9b4d-4a3e-8f7c-0d2a6e8b1c34",
      "packshot_id": "7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d",
      "status": "created"
    }
  ]
}

Remember product_ref (sklep1:produkt-7) — that's how you'll point to the product in step 4. Calling again with the same external_ref returns status: "existing" instead of creating a duplicate.

4. Order a photo session

You don't have to provide packshot_asset_id — when you omit it, the session uses the product's latest approved packshot (the one from step 3). You can pull the configuration (style, scenery, model) from the catalog — see the session parameters tutorial.

curl -X POST https://qamera.ai/api/v1/plugin/jobs \
  -H "X-Api-Key: mk_live_xxxxxxxx.yyyyyyyy" \
  -H "Idempotency-Key: sklep1-zamowienie-1001" \
  -H "Content-Type: application/json" \
  -d '{
    "session_config": { "aspect_ratio": "4:5" },
    "subjects": [
      {
        "product_label": "Kubek ceramiczny 300 ml",
        "product_ref": "sklep1:produkt-7",
        "images_count": 4,
        "ai_model": "byteplus/seedream-4.5"
      }
    ]
  }'

Response (HTTP 201):

{
  "order_id": "00000000-0000-0000-0000-000000000099",
  "status": "pending",
  "subjects": [
    {
      "product_ref": "sklep1:produkt-7",
      "job_ids": [
        "00000000-0000-0000-0000-0000000000a1",
        "00000000-0000-0000-0000-0000000000a2",
        "00000000-0000-0000-0000-0000000000a3",
        "00000000-0000-0000-0000-0000000000a4"
      ]
    }
  ]
}

Save order_id (the whole session) and job_ids (one job per image). The Idempotency-Key header ensures that re-sending the same request (e.g. after a timeout) won't create a second session.

Pull the ai_model value (a provider/model pair) from GET /ai-models the list depends on the merchant account's plan.

5. Receive the finished images

When a job finishes, we send a webhook to your installation's address — details in the receiving results tutorial. You can also poll:

curl https://qamera.ai/api/v1/plugin/jobs/00000000-0000-0000-0000-0000000000a1 \
  -H "X-Api-Key: mk_live_xxxxxxxx.yyyyyyyy"

A finished job has status: "completed" and an outputs[] list with the image download URLs. The URLs are valid for at least 7 days — after that, fetch fresh ones with POST /jobs/{id}/refresh-url.

6. (Optional) Rate the results

You can record the merchant's rating for each image. For a photo session this is pure feedback — it doesn't change credits or anything in the catalog.

curl -X POST https://qamera.ai/api/v1/plugin/jobs/00000000-0000-0000-0000-0000000000a1/accept \
  -H "X-Api-Key: mk_live_xxxxxxxx.yyyyyyyy"

Returns 204 No Content. The …/reject endpoint works the same way.

Common errors

ErrorWhy it happenedWhat to do
422 packshot_not_approvedThe product with product_ref has no approved packshot (e.g. a typo in product_ref, or the packshot wasn't registered)Check product_ref; make sure step 3 returned status: "created" or "existing"details
402 quota_exceededThe merchant account doesn't have enough credits for the sessionThe merchant needs to top up credits; check the account balance with GET /medetails
409 idempotency_conflictThe same Idempotency-Key used with a different bodyUse a new key for a new request — details
409 job_not_completedA rating (accept/reject) was sent before the job finishedWait for status: "completed"details
403 forbiddenThe key lacks the required permissionGenerate a key with the permissions from the "Prerequisites" section — details
413 on uploadThe file is larger than 50 MBShrink the file before uploading

Next steps