Process one public webpage
Submit a Single Page job and poll its status until image results are ready.
Submit a public webpage, process a list of exact URLs, or discover products in a supported public store. Retrieve image results and verified larger public versions when available, then download the files.
API keys are included with Pro, Business, and Scale. Pro can scan webpages, process URL lists, and preview Store Catalog products. Business and Scale can also process catalog products. API processing shares monthly website credits at 2 credits per successful webpage or catalog product, with no separate API subscription. The website’s free Single Page allowance does not apply to API requests.
Submit a Single Page job and poll its status until image results are ready.
Submit Multiple URLs runs for the exact public webpages you provide, without catalog discovery.
Preview compatible public ecommerce catalogs on Pro or higher. Process selected products with Business or Scale.
Read image URLs, dimensions, labels, formats, and verified public larger versions without AI upscaling.
Download page, URL-list, or catalog results. Inspect file counts and retry image downloads that failed.
Cancel unfinished jobs or runs, retry failed or unfinished pages, and keep completed results.
API v1.3 covers Single Page, Multiple URLs, and Store Catalog. Pro can preview catalogs through the API without processing credits. Business and Scale can also process selected catalog products. Version 1 uses polling rather than webhooks and does not include official SDKs.
Authorization: Bearer header. Keep it on your server, outside browser JavaScript and URLs.Use https://sourceimagefinder.com/api/v1 on the deployed site. For local testing, use http://127.0.0.1:8787/api/v1. For local testing, plan access comes from your development settings.
Every processing request needs an Idempotency-Key. Generate a new UUID for a new scan and reuse that UUID only when retrying the same request.
curl https://sourceimagefinder.com/api/v1/jobs \
-H "Authorization: Bearer $SIF_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: your-unique-request-uuid" \
-d '{"url":"https://example.com/page"}'
A successful submission returns 202 Accepted and a receipt:
{
"id": "11111111-1111-4111-8111-111111111111",
"type": "job",
"links": {"self": "/api/v1/jobs/11111111-1111-4111-8111-111111111111"}
}
Poll the returned path every 2 to 5 seconds. A job moves from queued to processing, then completed, failed, or cancelled. A completed scan may contain zero images. That still counts as successful page processing.
curl "https://sourceimagefinder.com/api/v1/jobs/JOB_ID" \
-H "Authorization: Bearer $SIF_API_KEY"
curl "https://sourceimagefinder.com/api/v1/jobs/JOB_ID/results?scope=useful&limit=100" \
-H "Authorization: Bearer $SIF_API_KEY"
curl "https://sourceimagefinder.com/api/v1/jobs/JOB_ID/zip" \
-H "Authorization: Bearer $SIF_API_KEY" \
-H "Content-Type: application/json" \
-d '{}' --output images.zip
Only save a response as a ZIP when its HTTP status is 200 and its content type is application/zip. Use the Node.js or PowerShell examples included in the application package for a complete submission, polling, and download flow.
Download filenames: ZIP responses include a Content-Disposition attachment filename, such as allbirds-com-product-images-322b7ecf1234-08af2a4283.zip. Use this header instead of a hardcoded filename. Names distinguish source or workflow, run, export settings/selection, split part, completed-only exports, and failed-file retries. The same export keeps its filename when downloaded again; choose a new local name when preserving multiple copies. The included Node and PowerShell examples read the header and avoid overwriting local ZIP files.
The included PowerShell examples accept -BaseUrl, so you can set the server address directly without relying on the SIF_BASE_URL environment variable in a new terminal. They show the server address in use and include API error details when a request fails.
$env:SIF_API_KEY = Get-Clipboard
.\examples\api-v1.ps1 -Url 'https://example.com/page' -BaseUrl 'http://127.0.0.1:8787'
.\examples\api-v1-bulk.ps1 -Urls 'https://example.com/a','https://example.com/b' -BaseUrl 'http://127.0.0.1:8787'
| Method and path | Purpose | Permission |
|---|---|---|
POST /catalog/previews | Create a public-store preview (no scan credits). | jobs:read |
GET /catalog/previews/{id}?page=1 | Read ten products per page of your retained preview. | jobs:read |
POST /catalog/jobs | Process explicit product handles from a preview. Business/Scale. Idempotency-Key required. | jobs:write |
GET /catalog/jobs/{id} | Monitor processing, failures and credit-relevant product statuses. | jobs:read |
POST /catalog/jobs/{id}/retry-failed | Retry failed products only, without charging for failures. | jobs:write |
POST /catalog/jobs/{id}/cancel | Cancel unfinished products. | jobs:write |
POST /catalog/jobs/{id}/zip | Download organized completed product images; use part when split. | downloads:read |
GET /usage | Shared credit balance, reset date, payment status, and limits. | jobs:read |
POST /jobs | Submit {"url":"https://example.com/page"}. | jobs:write |
POST /bulk | Submit {"urls":["https://example.com/a","https://example.com/b"]}. Only those pages are processed. | jobs:write |
GET /bulk/{id} | Read run status and the ordered page list. Each entry includes its job ID and webpage URL. | jobs:read |
POST /bulk/{id}/cancel | Send {} to stop unfinished pages while keeping completed results. | jobs:write |
POST /bulk/{id}/retry-failed | Send {} after the run finishes to retry only failed pages. | jobs:write |
POST /bulk/{id}/retry-unfinished | Send {} after the run finishes to retry failed or cancelled pages. | jobs:write |
POST /bulk/{id}/zip | Download completed pages together. Optionally send job_ids, mode, and part. | downloads:read |
GET /jobs/{id} | Read job status, progress, expiry, and result links. | jobs:read |
GET /jobs/{id}/results | Read image metadata. Results default to scope=useful; use scope=all to include site UI and review media. Use offset and limit for pagination. | jobs:read |
POST /jobs/{id}/cancel | Send {} to cancel one unfinished page job. | jobs:write |
POST /jobs/{id}/zip | Send {} for useful images, or {"image_ids":["IMAGE_ID"]} for selected images. Returns receipt headers. | downloads:read |
GET /downloads/{id} | Check a ZIP receipt: planned, included, failed, completeness and retry availability. | downloads:read |
POST /downloads/{id}/retry | Send {} to download only failed image files from a previous ZIP. | downloads:read |
Paths above are relative to /api/v1. All POST bodies must be JSON objects with Content-Type: application/json. Undocumented body fields and query parameters are rejected. Responses are private and should not be cached. Browser sessions cannot authenticate these endpoints.
Resetting your password revokes your API keys. Create new keys afterward to reconnect your scripts.
Keys can access their account’s Single Page and Multiple URLs jobs, including owned jobs started on the website. Pro or higher can create and read owned Store Catalog API previews. Business and Scale can also start and manage owned catalog runs. API keys cannot manage billing or create other keys. Multiple URLs API runs support run-level cancellation, failed/unfinished retry, and combined ZIP downloads. Cancelling a run removes its queued pages first, then stops active pages; queued pages cancelled before processing starts use no credits, while pages that already started can still use their normal 2-credit charge. Version 1 uses polling; it does not include completion webhooks or official SDKs.
Pro, Business, and Scale accounts can preview supported public ecommerce catalogs with an API key. Business and Scale can select exact product handles, start processing, and download product-organized ZIP files. API catalog previews use no processing credits. Processing reserves two credits per selected product and consumes two only for each successful product; failures release their reservation. Existing public store data discovery and platform restrictions apply. Business allows 250 selected products per run; Scale allows 1,000.
The API uses the same public Store Catalog discovery paths as the website, with tested patterns for Shopify, WooCommerce, Wix Stores, PrestaShop, BigCommerce, Magento / Adobe Commerce, Shopware 6, and OpenCart. Platform support varies by public URL, theme, and available store data; a successful preview is not guaranteed on every storefront. Squarespace product-page image scanning is available, but Store Catalog discovery is conditional, not a dedicated Squarespace adapter. See supported ecommerce platforms and URL types before processing a catalog.
POST /api/v1/catalog/previews
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{"url":"https://example.com/collections/all"}
GET /api/v1/catalog/previews/PREVIEW_ID?page=1
Authorization: Bearer YOUR_API_KEY
POST /api/v1/catalog/jobs
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Idempotency-Key: NEW_UNIQUE_KEY
{"preview_id":"PREVIEW_ID","product_handles":["product-handle-1"]}
GET /api/v1/catalog/jobs/RUN_ID
Authorization: Bearer YOUR_API_KEY
POST /api/v1/catalog/jobs/RUN_ID/zip
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{"mode":"focused"}
Previews are owner-bound, retain their selected products for up to 24 hours, and return 10 products per page. Only product handles present in the same account's preview can be submitted, and the store is rediscovered before work starts. Failed product retries use POST /catalog/jobs/{id}/retry-failed with {}; cancelled runs cannot use failed-only retry. The ZIP includes completed products after all members finish. Inspect X-SIF-Download-ID to check completeness and retry any failed image-file downloads at no additional scan-credit cost. ZIP receipt state lives for up to 30 minutes in memory, whereas catalog scan results remain accessible for 24 hours.
Examples: examples/api-v13-catalog.mjs and examples/api-v13-catalog.ps1.
POST /jobs/{id}/zip and POST /bulk/{id}/zip return an X-SIF-Download-ID header with the ZIP stream. The matching X-SIF-Download-Status header is a relative link to GET /api/v1/downloads/{id}. Use the same Bearer API key with downloads:read permission.
GET /api/v1/downloads/DOWNLOAD_ID
Authorization: Bearer YOUR_API_KEY
{ "download": { "state": "ready", "totalFiles": 25, "includedFiles": 23, "failedFiles": 2,
"complete": false, "retryAvailable": true, "failures": [ ... ], "expiresAt": "..." } }
If retryAvailable is true, call POST /api/v1/downloads/DOWNLOAD_ID/retry with {} and save the returned ZIP separately. It contains only images that failed in the prior attempt. Query the same receipt again for updated counts. ZIP retries cost no additional scan credits and do not rescan webpages. For Single Page product images, an explicit failed-file retry may include a separately named previously verified alternative if the exact selected file still cannot be downloaded. In that case the additive alternativeFiles receipt count reports fulfilled selections delivered as alternatives, and the retry ZIP contains verified-alternatives.csv; the original requested file is not silently replaced. They count against the ZIP-build rate limit.
Receipts are held in server memory for up to 30 minutes after their latest update and are lost on server restart. Jobs must also remain within the 24-hour result retention window. A status check may return 404 when a receipt is gone; recreate the original ZIP to get a fresh receipt. A completed ZIP download does not guarantee complete: true, so check the receipt when file completeness matters.
GET /jobs/{id} returns a job object. GET /jobs/{id}/results returns the page title, requested and final URLs, scan time, expiry, the active result scope, an images array, and a pagination object. The default scope=useful excludes site-ui and review-media so the JSON result matches the normal downloadable image set more closely. Use scope=all when you need every detected asset. Pagination counts and next_offset apply to the selected scope. The default page size is 100 images; the maximum is 500.
GET /api/v1/jobs/JOB_ID/results?scope=useful&limit=100
GET /api/v1/jobs/JOB_ID/results?scope=all&limit=100
{
"id": "image-family-id",
"category": "product-gallery",
"label": "SOURCE RECOVERED",
"alt_text": "Example product",
"product_linked": true,
"variant_ids": [],
"page_max": {"url":"https://example.com/small.jpg", "width":400, "height":400, "format":"jpeg", "bytes":18000},
"best": {"url":"https://example.com/large.jpg", "width":1400, "height":1400, "format":"jpeg", "bytes":170000, "verdict":"source-recovered"},
"pixel_gain": 12.25,
"page_versions": []
}
PAGE MAX is the best version verified from the image links on the page. SOURCE RECOVERED means a better public version was found and verified. BEST AVAILABLE reports the best verified file found without claiming a recovered original. POSSIBLE BETTER VERSION is not proof of a verified improvement. Inspect best.verdict instead of assuming every result is a recovered original. No AI upscaling is performed.
Source URLs belong to the source website and may later change or stop working. Download files before the result expires. ZIPs keep the source file formats. They exclude review/customer-upload media; the default also excludes site UI. Explicit image IDs can include site UI. ZIPs can include a failure report when a source file is no longer available. For Multiple URLs, POST /bulk/{id}/zip can combine completed pages. Use job_ids to select pages and mode as focused or all-useful. If an export must be split, the API returns download_split_required with the number of parts; repeat the request with part set to 1 through that number.
| Plan | Monthly price | Monthly credits | URLs per run | Catalog products per run | Active Single Page jobs |
|---|---|---|---|---|---|
| Pro | $9 | 1,000 | 25 | Preview only | 2 |
| Business | $29 | 4,000 | 250 | 250 | 4 |
| Scale | $99 | 16,000 | 1,000 | 1,000 | 8 |
All prices are USD per month. API access is included in each listed paid plan, without a separate API fee. These are the default plan limits; GET /usage returns the account’s configured webpage limits. There is one active Multiple URLs run per account across API and website. Active Single Page limits also count that account’s website jobs. Jobs share the website’s processing queue, so submission limits do not guarantee simultaneous execution.
X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset for the last applicable limit. Reset is Unix time in seconds. On HTTP 429, follow Retry-After.expires_at for its expiry time. Download early pages in a long bulk run promptly. HTTP 410 means expired; after cleanup the same ID may return 404.billing_refresh_required is true, the displayed usage belongs to the previous billing period. The server verifies the current subscription before accepting new paid work.{"error":{"code":"insufficient_credits","message":"This run needs 2 credits, but only 0 remain in this credit period","request_id":"request-uuid"}}| HTTP | Common codes | What to do |
|---|---|---|
| 400 / 415 | invalid_request, invalid_url, invalid_json, invalid_pagination, idempotency_key_required, invalid_idempotency_key, unsupported_media_type, plan_limit_exceeded | Fix the request or reduce its size. |
| 401 / 403 | invalid_api_key, insufficient_scope, plan_required | Check the key, permissions, and your plan. |
| 402 | insufficient_credits, payment_required | Check credits or billing. |
| 404 / 410 | not_found, download_not_found, result_expired | Check the ID and account, or start a new scan. |
| 405 | method_not_allowed | Use the method in the Allow header. |
| 409 | job_not_ready, no_failed_files, download_building, retry_limit_exceeded, run_active, retry_unfinished_required, nothing_to_retry, download_split_required, concurrency_limit, idempotency_conflict, request_incomplete, idempotency_capacity, conflict | Wait for active work, choose the correct retry action or ZIP part, or correct a conflicting retry. |
| 400 / 413 | download_unavailable, download_too_large, request_too_large | Select fewer images or send a smaller request. |
| 422 / 502 / 504 | unprocessable_source, upstream_error, timeout | Check that the public source is supported, or retry after a temporary upstream failure. |
| 429 / 503 / 500 | rate_limit_exceeded, service_unavailable, internal_error | Back off. Retry processing with the same Idempotency-Key. |
Successful processing receipts can be replayed for 24 hours from submission, even across a server restart or a rotated key belonging to the same account. Idempotency-Replayed: true identifies a replay. Reusing a key for another request returns 409. A retry after 24 hours may create a new paid scan. A verified failure before jobs or credits were created can be retried after the problem is fixed.
If a server interruption leaves an uncertain submission, the server preserves its retry record and returns request_incomplete until it can recover the original job IDs. Do not switch to a new key to get around this error; check usage and contact support with request_id. A successful receipt confirms submission, not completed extraction.
Version 1 may add response fields. Clients should ignore unknown response fields. Breaking changes use a new versioned path. Use the OpenAPI document as the machine-readable contract.