Skip to main content
When you need to analyze multiple shelf photos — for example, every aisle in a store or photos from a field team’s daily route — use the batch endpoint to submit up to 20 images in a single request.

When to use batch

  • Processing a set of photos from a single store visit
  • Analyzing images uploaded by field teams throughout the day
  • Running periodic audits across multiple locations
  • Any workflow where you have multiple images ready to submit at once

Submitting a batch

Send a POST request to the batch analyses endpoint with an array of images:
curl -X POST https://shelfforce.ai/api/v1/analyses/batch \
  -H "Authorization: Bearer sf_live_a1b2c3d4..." \
  -H "Content-Type: application/json" \
  -d '{
    "images": [
      {
        "imageUrl": "https://example.com/store-42/aisle-1.jpg",
        "metadata": { "store": "store-42", "aisle": "1" }
      },
      {
        "imageUrl": "https://example.com/store-42/aisle-2.jpg",
        "metadata": { "store": "store-42", "aisle": "2" }
      },
      {
        "imageUrl": "https://example.com/store-42/aisle-3.jpg",
        "metadata": { "store": "store-42", "aisle": "3" }
      }
    ]
  }'

Request parameters

ParameterTypeRequiredDescription
imagesarrayYesArray of image objects. Max size depends on your plan tier (see Limits).
images[].imageUrlstringYesPublicly accessible URL of the shelf image.
images[].externalIdstringNoYour own reference ID for this image (e.g., customer ID, campaign ID).
images[].metadataobjectNoArbitrary key-value pairs (max 10 keys, string values, 500 chars each).
images[].placeIdstringNoShelfforce place ID to associate with this image.
images[].taskIdstringNoShelfforce task ID to associate with this image.
callbackUrlstringNoHTTPS URL to receive a POST for each completed/failed analysis. A callbackSecret is returned per analysis for signature verification.

Response

{
  "batchId": "batch_1a2b3c4d",
  "analyses": [
    {
      "id": "an_001",
      "status": "processing",
      "imageUrl": "https://example.com/store-42/aisle-1.jpg",
      "metadata": { "store": "store-42", "aisle": "1" }
    },
    {
      "id": "an_002",
      "status": "processing",
      "imageUrl": "https://example.com/store-42/aisle-2.jpg",
      "metadata": { "store": "store-42", "aisle": "2" }
    },
    {
      "id": "an_003",
      "status": "processing",
      "imageUrl": "https://example.com/store-42/aisle-3.jpg",
      "metadata": { "store": "store-42", "aisle": "3" }
    }
  ],
  "creditsConsumed": 3,
  "createdAt": "2026-02-23T10:30:00Z"
}
Each image in the batch creates a separate analysis with its own ID. The analyses run in parallel.

Credit handling

Batch analysis uses an all-or-nothing credit check:
  • Each image costs 1 credit (same as a single analysis).
  • Before processing begins, Shelfforce verifies you have enough credits for the entire batch.
  • If you do not have enough credits, the entire request is rejected — no images are analyzed and no credits are consumed.
// Submitting 10 images with only 5 credits remaining:
{
  "error": {
    "code": "INSUFFICIENT_CREDITS",
    "message": "Insufficient credits. This batch requires 10 credits but you have 5 remaining.",
    "details": {
      "required": 10,
      "available": 5
    }
  }
}

Retrieving results

Each analysis in the batch has its own ID. Poll individual analyses for results:
curl https://shelfforce.ai/api/v1/analyses/an_001 \
  -H "Authorization: Bearer sf_live_a1b2c3d4..."
Or use webhooks to be notified as each analysis completes. If you provided a callbackUrl in the batch request, you will receive a separate webhook for each image as it finishes.

Checking batch status

You can also query the batch endpoint to see the status of all analyses in the batch:
curl https://shelfforce.ai/api/v1/analyses/batch/batch_1a2b3c4d \
  -H "Authorization: Bearer sf_live_a1b2c3d4..."
{
  "batchId": "batch_1a2b3c4d",
  "status": "partial",
  "total": 3,
  "completed": 2,
  "processing": 1,
  "failed": 0,
  "analyses": [
    { "id": "an_001", "status": "completed" },
    { "id": "an_002", "status": "completed" },
    { "id": "an_003", "status": "processing" }
  ]
}
The batch status is one of:
  • processing — All analyses are still running.
  • partial — Some analyses have completed, others are still running.
  • completed — All analyses have finished (either completed or failed).

Idempotency keys

Use idempotency keys to safely retry batch requests without creating duplicate analyses. If a request with the same idempotency key is submitted again, Shelfforce returns the existing analysis instead of creating a new one.
{
  "images": [
    {
      "imageUrl": "https://example.com/shelf.jpg",
      "idempotencyKey": "store-42-aisle-1-2026-02-23"
    }
  ]
}
Idempotency keys are scoped to your organisation and expire after 24 hours. Use a combination of store, location, and date to create meaningful keys.

Best practices

Group by store visit

Submit all photos from a single store visit in one batch. This makes it easy to correlate results and reduces API calls.

Use metadata

Attach store IDs, aisle numbers, and dates as metadata so you can filter and group results later.

Use idempotency keys

Always include idempotency keys, especially when retrying failed requests or when your pipeline might submit the same image twice.

Combine with webhooks

Set a callbackUrl on the batch or register a persistent webhook for analysis.completed to avoid polling each analysis individually.

Limits

The maximum number of images per batch depends on your plan tier:
PlanMax images per batch
Free20
Starter20
Growth50
Pro100
Scale200
You can check your current batch limit programmatically via GET /api/v1/usage — the response includes a maxBatchSize field.
ConstraintValue
Maximum image file size20 MB
Supported formatsJPEG, PNG, WebP
If you need to process more images than your tier allows, split them into multiple batch requests. Use idempotency keys to prevent duplicates if you are retrying.