All endpoints (except /health) require Bearer authentication using the Authorization header:
Authorization: Bearer <your-api-key>
Check the health status of the application.
Endpoint: GET /health
Authentication: Not required
Response:
{
"status": "ok",
"timestamp": "2025-01-01T12:00:00.000Z",
"queue_stats": {
"total": 10,
"pending": 2,
"running": 1,
"completed": 6,
"failed": 1
}
}
Create a new scraping job for a webshop.
Endpoint: POST /api/jobs
Request Body:
{
"url": "https://example-shop.com"
}
Response: 201 Created
{
"job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"shop_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "pending",
"message": "Job created successfully"
}
Error Responses:
400 Bad Request - Missing or invalid URL500 Internal Server Error - Server errorExample:
curl -X POST http://localhost:3000/api/jobs \
-H "Authorization: Bearer your-secret-key" \
-H "Content-Type: application/json" \
-d '{"url": "https://example-shop.com"}'
Get the status and result of a specific job.
Endpoint: GET /api/jobs/:id
URL Parameters:
id - Job UUIDResponse:
{
"job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "completed",
"created_at": "2025-01-01T12:00:00.000Z",
"updated_at": "2025-01-01T12:05:00.000Z",
"result": {
"initial_sitemap": "https://example-shop.com/sitemap.xml",
"shipping_informations": [
{
"url": "https://example-shop.com/shipping",
"content": "# Shipping Information\n\n..."
}
],
"contacts": [
{
"url": "https://example-shop.com/contact",
"content": "# Contact Us\n\n..."
}
],
"terms_of_conditions": [
{
"url": "https://example-shop.com/terms",
"content": "# Terms and Conditions\n\n..."
}
],
"faq": [
{
"url": "https://example-shop.com/faq",
"content": "# FAQ\n\n..."
}
]
}
}
Status Values:
pending - Job is waiting in queuerunning - Job is currently being processedcompleted - Job finished successfullyfailed - Job failed (includes error field)Error Responses:
404 Not Found - Job not found500 Internal Server Error - Server errorExample:
curl http://localhost:3000/api/jobs/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
-H "Authorization: Bearer your-secret-key"
Get a list of all jobs with queue statistics.
Endpoint: GET /api/jobs
Response:
{
"stats": {
"total": 10,
"pending": 2,
"running": 1,
"completed": 6,
"failed": 1
},
"jobs": [
{
"job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "completed",
"sitemap_url": "https://example-shop.com",
"created_at": "2025-01-01T12:00:00.000Z",
"updated_at": "2025-01-01T12:05:00.000Z"
}
]
}
Example:
curl http://localhost:3000/api/jobs \
-H "Authorization: Bearer your-secret-key"
Get a list of all shops with their analytics.
Endpoint: GET /api/shops
Response:
{
"shops": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"url": "https://example-shop.com",
"sitemap_url": "https://example-shop.com/sitemap.xml",
"webshop_type": "shopify",
"created_at": "2025-01-01T10:00:00.000Z",
"updated_at": "2025-01-01T12:00:00.000Z",
"analytics": {
"total_scrapes": 5,
"last_scraped_at": "2025-01-01T12:00:00.000Z",
"next_scrape_at": "2025-01-02T12:00:00.000Z",
"total_urls_found": 42,
"average_scrape_time": 5432.5,
"average_page_scrape_time": 234.8
}
}
]
}
Error Responses:
503 Service Unavailable - Database not available500 Internal Server Error - Server errorExample:
curl http://localhost:3000/api/shops \
-H "Authorization: Bearer your-secret-key"
Get detailed information about a specific shop including analytics, content metadata, scrape history, and scheduled jobs.
Endpoint: GET /api/shops/:id
URL Parameters:
id - Shop UUIDResponse:
{
"shop": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"url": "https://example-shop.com",
"sitemap_url": "https://example-shop.com/sitemap.xml",
"webshop_type": "shopify",
"created_at": "2025-01-01T10:00:00.000Z",
"updated_at": "2025-01-01T12:00:00.000Z"
},
"analytics": {
"total_scrapes": 5,
"last_scraped_at": "2025-01-01T12:00:00.000Z",
"next_scrape_at": "2025-01-02T12:00:00.000Z",
"total_urls_found": 42,
"average_scrape_time": 5432.5,
"average_page_scrape_time": 234.8
},
"content_metadata": {
"shipping_informations": [
{
"url": "https://example-shop.com/shipping",
"changed": false,
"last_updated": "2025-01-01T12:00:00.000Z"
}
],
"contacts": [
{
"url": "https://example-shop.com/contact",
"changed": true,
"last_updated": "2025-01-01T12:00:00.000Z"
}
],
"terms_of_conditions": [],
"faq": []
},
"scrape_history": [
{
"id": "history-uuid-1",
"job_id": "job-uuid-1",
"started_at": "2025-01-01T12:00:00.000Z",
"completed_at": "2025-01-01T12:05:00.000Z",
"status": "completed",
"error": null,
"scrape_time_ms": 5432,
"urls_found": 42
}
],
"scheduled_jobs": [
{
"id": "schedule-uuid-1",
"next_run_at": "2025-01-02T12:00:00.000Z",
"frequency": "daily",
"last_modified": "2025-01-01T10:00:00.000Z",
"status": "pending",
"enabled": true,
"created_at": "2025-01-01T10:00:00.000Z"
}
]
}
Notes:
/api/shops/:id/results endpointchanged flag indicates if content has changed since the previous scrapeError Responses:
404 Not Found - Shop not found503 Service Unavailable - Database not available500 Internal Server Error - Server errorExample:
curl http://localhost:3000/api/shops/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer your-secret-key"
Get shop scraping results with full content. Supports filtering by date range, content type, and limit.
Endpoint: GET /api/shops/:id/results
URL Parameters:
id - Shop UUIDQuery Parameters:
limit (optional) - Maximum number of results to returndate_from (optional) - Filter results from this date (ISO 8601 format)date_to (optional) - Filter results to this date (ISO 8601 format)content_type (optional) - Filter by content type: shipping, contacts, terms, or faqResponse:
{
"shop_id": "550e8400-e29b-41d4-a716-446655440000",
"filters": {
"limit": 10,
"date_from": "2025-01-01",
"date_to": null,
"content_type": null
},
"results": {
"shipping_informations": [
{
"url": "https://example-shop.com/shipping",
"content": "# Shipping Information\n\nDetailed shipping content...",
"changed": false,
"last_updated": "2025-01-01T12:00:00.000Z"
},
{
"url": "https://example-shop.com/delivery-info",
"content": "# Delivery Information\n\nDetailed delivery content...",
"changed": true,
"last_updated": "2025-01-01T12:00:00.000Z"
}
],
"contacts": [
{
"url": "https://example-shop.com/contact",
"content": "# Contact Us\n\nEmail: contact@example.com\nPhone: +1234567890",
"changed": true,
"last_updated": "2025-01-01T12:00:00.000Z"
}
],
"terms_of_conditions": [
{
"url": "https://example-shop.com/terms",
"content": "# Terms and Conditions\n\nDetailed terms...",
"changed": false,
"last_updated": "2025-01-01T12:00:00.000Z"
}
],
"faq": [
{
"url": "https://example-shop.com/faq",
"content": "# Frequently Asked Questions\n\nQ: Question 1?\nA: Answer 1...",
"changed": false,
"last_updated": "2025-01-01T12:00:00.000Z"
}
]
}
}
Notes:
changed flag indicates if content has changed since the previous scrapeError Responses:
404 Not Found - Shop not found503 Service Unavailable - Database not available500 Internal Server Error - Server errorExamples:
Get all results:
curl "http://localhost:3000/api/shops/550e8400-e29b-41d4-a716-446655440000/results" \
-H "Authorization: Bearer your-secret-key"
Get limited results:
curl "http://localhost:3000/api/shops/550e8400-e29b-41d4-a716-446655440000/results?limit=10" \
-H "Authorization: Bearer your-secret-key"
Get results from a specific date:
curl "http://localhost:3000/api/shops/550e8400-e29b-41d4-a716-446655440000/results?date_from=2025-01-01" \
-H "Authorization: Bearer your-secret-key"
Get only shipping information:
curl "http://localhost:3000/api/shops/550e8400-e29b-41d4-a716-446655440000/results?content_type=shipping" \
-H "Authorization: Bearer your-secret-key"
Get results with date range and limit:
curl "http://localhost:3000/api/shops/550e8400-e29b-41d4-a716-446655440000/results?date_from=2025-01-01&date_to=2025-01-31&limit=50" \
-H "Authorization: Bearer your-secret-key"
Enable or disable scheduled scraping for a shop.
Endpoint: PATCH /api/shops/:id/schedule
URL Parameters:
id - Shop UUIDRequest Body:
{
"enabled": true
}
Response:
{
"shop_id": "550e8400-e29b-41d4-a716-446655440000",
"schedule_enabled": true,
"message": "Schedule enabled successfully"
}
Error Responses:
400 Bad Request - Missing or invalid enabled field404 Not Found - Shop not found503 Service Unavailable - Database not available500 Internal Server Error - Server errorExamples:
Enable scheduling:
curl -X PATCH http://localhost:3000/api/shops/550e8400-e29b-41d4-a716-446655440000/schedule \
-H "Authorization: Bearer your-secret-key" \
-H "Content-Type: application/json" \
-d '{"enabled": true}'
Disable scheduling:
curl -X PATCH http://localhost:3000/api/shops/550e8400-e29b-41d4-a716-446655440000/schedule \
-H "Authorization: Bearer your-secret-key" \
-H "Content-Type: application/json" \
-d '{"enabled": false}'
Delete a shop and all related data (analytics, scrape history, content, scheduled jobs).
Endpoint: DELETE /api/shops/:id
URL Parameters:
id - Shop UUIDResponse:
{
"message": "Shop and all related data deleted successfully",
"shop_id": "550e8400-e29b-41d4-a716-446655440000"
}
Notes:
Error Responses:
404 Not Found - Shop not found503 Service Unavailable - Database not available500 Internal Server Error - Server errorExample:
curl -X DELETE http://localhost:3000/api/shops/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer your-secret-key"
All endpoints return standard HTTP status codes:
200 OK - Request successful201 Created - Resource created successfully400 Bad Request - Invalid request parameters404 Not Found - Resource not found500 Internal Server Error - Server error503 Service Unavailable - Service (e.g., database) unavailableError responses include a JSON body with an error field:
{
"error": "Description of the error"
}
The scraper categorizes content into four types:
Each category can contain multiple pages (returned as arrays).
The application automatically schedules scraping based on sitemap rules:
always, hourly, daily, weekly, monthly, yearlyThe system uses MD5 hashing to detect content changes:
changed flag set to true if hashes differ