Skip to main content
Shelf analysis is the core capability of the Shelfforce API. You submit an image of a retail shelf, and Shelfforce returns structured data for every product detected — including brand, description, category, facing count, price, promotional status, confidence score, and fixture type. This guide walks through the full analysis workflow.

How it works

Shelfforce uses a multi-step vision pipeline to analyze shelf images:
  1. Extraction — Identifies unique SKUs visible on the shelf.
  2. Product Detail — Determines facing counts and shelf positions for each product.
  3. Price Attribution — Reads all price tags and matches them to the correct products using spatial reasoning.
  4. Summary — Computes brand-level share-of-shelf metrics and totals.
The entire pipeline runs automatically when you submit an image. You receive the complete results when the analysis finishes.

The analysis lifecycle

Analysis is asynchronous. Here is exactly what happens from submission to results:
┌──────────────────────────────────────────────────────────────┐
│  1. POST /api/v1/analyses                                    │
│     You submit an image URL                                  │
│     → Response: { status: "processing", id: "an_..." }       │
│                                                              │
│  2. Processing (10-30 seconds)                               │
│     Shelfforce runs extraction → detail → pricing → summary  │
│                                                              │
│  3. Results ready                                            │
│     ┌─ Option A: Poll GET /api/v1/analyses/:id               │
│     │  Loop every 3-5s until status = "completed"            │
│     │  Best for: quick testing, scripts, simple integrations │
│     │                                                        │
│     ├─ Option B: Webhook notification                        │
│     │  Register for analysis.completed event                 │
│     │  Best for: production systems, high volume             │
│     │                                                        │
│     └─ Option C: Callback URL                                │
│        Pass callbackUrl in the request                       │
│        Best for: per-request notifications, B2B integrations │
│                                                              │
│  4. Read the products array from the completed response      │
└──────────────────────────────────────────────────────────────┘
Typical processing time: 10-30 seconds, depending on image complexity (number of products, price tag legibility, image resolution). High-resolution images with many products may take up to 45 seconds.
Which result method should I use?
  • Polling is simpler and great for scripts, CLI tools, and quick testing. Poll every 3-5 seconds.
  • Webhooks are more efficient for production. No wasted requests, instant notification. See Webhooks.

Step 1: Submit an image

Send a POST request to the analyses endpoint with the URL of a shelf image:
curl -X POST https://shelfforce.ai/api/v1/analyses \
  -H "Authorization: Bearer sf_live_a1b2c3d4..." \
  -H "Content-Type: application/json" \
  -d '{
    "imageUrl": "https://example.com/shelf.jpg"
  }'

Request parameters

ParameterTypeRequiredDescription
imageUrlstringYesPublicly accessible URL of the shelf image. JPEG, PNG, and WebP are supported.
placeIdstringNoShelfforce place ID to associate with this analysis.
taskIdstringNoShelfforce task ID to associate with this analysis.
externalIdstringNoYour own reference ID (e.g., customer ID, campaign ID). Returned in responses and webhook payloads. Filterable via the list analyses endpoint.
metadataobjectNoArbitrary key-value pairs (max 10 keys, string values, 500 chars each). Returned in responses and webhook payloads.
callbackUrlstringNoHTTPS URL to receive a POST when this analysis completes or fails. See Callback URLs.

Response

The response comes back immediately. The status is processing while the analysis runs.
{
  "data": {
    "id": "an_g7h8j9k0",
    "status": "processing",
    "createdAt": "2026-02-23T10:30:00Z"
  }
}
One credit is consumed per analysis submission. See Credits for details.

Step 2: Get the results

Option A: Polling

Poll the analysis endpoint until the status is completed:
curl https://shelfforce.ai/api/v1/analyses/an_g7h8j9k0 \
  -H "Authorization: Bearer sf_live_a1b2c3d4..."

Option B: Webhooks

Register a webhook for analysis.completed and Shelfforce will POST the result to your URL as soon as processing finishes. No polling needed.
# Register once
curl -X POST https://shelfforce.ai/api/v1/webhooks \
  -H "Authorization: Bearer sf_live_a1b2c3d4..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/shelfforce",
    "events": ["analysis.completed", "analysis.failed"]
  }'
When the analysis completes, you receive a POST like this:
{
  "event": "analysis.completed",
  "data": {
    "generationId": "an_g7h8j9k0",
    "status": "completed",
    "productCount": 12,
    "createdAt": "2026-02-23T10:30:00Z"
  },
  "timestamp": "2026-02-23T10:32:00Z",
  "webhookId": "wh_abc123"
}
Then fetch the full results using the generationId:
curl https://shelfforce.ai/api/v1/analyses/an_g7h8j9k0 \
  -H "Authorization: Bearer sf_live_a1b2c3d4..."
See the Webhooks guide for full setup, payload examples, signature verification, and receiver code.

Option C: Callback URL

Pass a callbackUrl when submitting an analysis to receive a one-off POST when it completes — no webhook registration needed.
curl -X POST https://shelfforce.ai/api/v1/analyses \
  -H "Authorization: Bearer sf_live_a1b2c3d4..." \
  -H "Content-Type: application/json" \
  -d '{
    "imageUrl": "https://example.com/shelf.jpg",
    "externalId": "customer-123",
    "callbackUrl": "https://your-app.com/callbacks/shelfforce"
  }'
The response includes a callbackSecret you can use to verify the callback signature:
{
  "data": {
    "id": "an_g7h8j9k0",
    "status": "processing",
    "externalId": "customer-123",
    "callbackSecret": "a1b2c3d4e5f6...",
    "createdAt": "2026-02-23T10:30:00Z"
  }
}
The callbackSecret is returned only once. Store it to verify the callback signature using the same HMAC-SHA256 scheme as webhooks.
The callback URL must be HTTPS and cannot target private networks (localhost, 10.x, 192.168.x, etc.).

List analyses

Query your analyses with filters using GET /api/v1/analyses:
# Filter by externalId
curl "https://shelfforce.ai/api/v1/analyses?externalId=customer-123" \
  -H "Authorization: Bearer sf_live_a1b2c3d4..."

# Filter by status
curl "https://shelfforce.ai/api/v1/analyses?status=completed&limit=50" \
  -H "Authorization: Bearer sf_live_a1b2c3d4..."
ParameterTypeDescription
externalIdstringFilter by your external reference ID.
statusstringFilter by status: processing, completed, failed.
placeIdstringFilter by place ID.
cursorstringPagination cursor from a previous response.
limitintegerMax results per page (default 50, max 100).

Completed response

{
  "data": {
    "id": "an_g7h8j9k0",
    "status": "completed",
    "totalRuns": 1,
    "completedRuns": 1,
    "failedRuns": 0,
    "productCount": 12,
    "createdAt": "2026-02-23T10:30:00Z",
    "completedAt": "2026-02-23T10:32:00Z",
    "products": [
      {
        "id": "prd_k1l2m3",
        "sku": "CC-330ML-CAN",
        "brand": "Coca-Cola",
        "description": "Coca-Cola Original 330ml Can",
        "category": "Beverages",
        "subcategory": "Carbonated Soft Drinks",
        "price": 1.49,
        "currency": "USD",
        "onSale": false,
        "units": 4,
        "confidence": 0.95,
        "shelfPosition": "eye-level",
        "fixtureType": "shelf"
      }
    ]
  }
}

Step 3: Work with product data

Product fields

Each product in the products array includes:
FieldTypeDescription
idstringUnique product detection identifier
skustring | nullMatched SKU from your inventory, if identified
brandstringDetected brand name
descriptionstringFull product description as detected on shelf
categorystring | nullProduct category
subcategorystring | nullProduct subcategory
pricenumber | nullDetected shelf price. Null if no price tag was found
discountedPricenumber | nullPromotional/sale price if on sale
currencystring | nullISO 4217 currency code
onSaleboolean | nullWhether the product appears to be on promotion
unitsnumberNumber of visible facings on the shelf
confidencenumber | nullDetection confidence score (0.0 to 1.0)
shelfPositionstring | nullVertical position: top, eye-level, middle, bottom
fixtureTypestring | nullWhere the product was found: shelf, fridge, floor-display, other

Query products across analyses

To retrieve products across multiple analyses, use the products endpoint with optional filters:
# By analysis
curl "https://shelfforce.ai/api/v1/products?analysisId=an_g7h8j9k0" \
  -H "Authorization: Bearer sf_live_a1b2c3d4..."

# By brand
curl "https://shelfforce.ai/api/v1/products?brand=Coca-Cola" \
  -H "Authorization: Bearer sf_live_a1b2c3d4..."

# With pagination
curl "https://shelfforce.ai/api/v1/products?limit=50" \
  -H "Authorization: Bearer sf_live_a1b2c3d4..."

Step 4: View reports

Query aggregated share-of-shelf reports:
curl "https://shelfforce.ai/api/v1/reports/share-of-shelf?days=30&brands=Coca-Cola,Pepsi" \
  -H "Authorization: Bearer sf_live_a1b2c3d4..."
{
  "data": {
    "brands": [
      {
        "brand": "Coca-Cola",
        "units": 342,
        "sharePercent": 28.5,
        "productCount": 8
      },
      {
        "brand": "Pepsi",
        "units": 288,
        "sharePercent": 24.0,
        "productCount": 6
      }
    ],
    "totalUnits": 1200,
    "periodDays": 30,
    "periodStart": "2026-01-24T00:00:00Z",
    "periodEnd": "2026-02-23T23:59:59Z"
  }
}

Image requirements

For best results, follow these guidelines when capturing shelf images:

Do

  • Capture the full shelf section in frame
  • Ensure products and price tags are legible
  • Use good lighting with minimal glare
  • Shoot from directly in front of the shelf

Avoid

  • Blurry or out-of-focus images
  • Extreme angles that distort product labels
  • Heavy shadows or reflections obscuring products
  • Partial shelf captures that cut off products
Supported formats: JPEG, PNG, WebP Recommended resolution: 1920x1080 or higher. Higher resolution images produce more accurate results, especially for reading price tags.

Analysis statuses

StatusDescription
processingThe analysis is running. Poll again or wait for a webhook.
completedThe analysis finished successfully. Products and summary are available.
failedThe analysis could not produce results. Check the error field for details.

Next steps

Batch Analysis

Process up to 20 images in a single request.

Webhooks

Get notified when analyses complete instead of polling.

Field Operations

Assign shelf audits to field reps and track compliance.

Agent Integration

Connect Shelfforce to AI agents and automated pipelines.