No credit card required
Get started for free
Save time and avoid manual screenshot hassle — keep your docs and helpdesk perfectly up to date with automated, consistent visuals that impress users and cut support requests.
Get started nowComplete reference for all FreshShots API endpoints, including authentication, parameters, and response formats.
FreshShots uses API key authentication for public endpoints. Include your API key in the request header:
curl -H "x-api-key: YOUR_API_KEY_HERE" \
-H "Content-Type: application/json" \
https://api.freshshots.io/v1/...
https://api.freshshots.io
Execute a workflow programmatically and optionally receive webhook notifications when complete.
Endpoint: POST /v1/run/{workflow_id}
Parameters:
workflow_id
(path, required): Your workflow ID numberRequest Body:
{
"webhook_url": "https://your-server.com/webhook"
}
Example Request:
curl -X POST https://api.freshshots.io/v1/run/123 \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"webhook_url": "https://example.com/webhook"}'
Response (202 Accepted):
{
"job_id": 456,
"status": "pending",
"estimated_time": 45
}
Error Responses:
400
: Invalid workflow_id or webhook URL format401
: Missing API key403
: Invalid API key or workflow not accessible404
: Workflow not foundCheck the status and results of a workflow execution.
Endpoint: GET /v1/job/{job_id}
Parameters:
job_id
(path, required): Job ID returned from workflow triggerExample Request:
curl -X GET https://api.freshshots.io/v1/job/456 \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json"
Response (200 OK):
{
"job_id": 456,
"workflow_id": 123,
"status": "completed",
"device": "Desktop Chrome",
"completed_at": "2025-01-15T10:30:00Z",
"processing_time": 42,
"screenshots": [
{
"file_name": "homepage.png",
"url": "https://cdn.freshshots.io/1/homepage.png"
},
{
"file_name": "login-form.png",
"url": "https://cdn.freshshots.io/1/login-form.png"
}
]
}
Job Status Values:
pending
: Job is queued and waiting to be processedrunning
: Job is currently being executedcompleted
: Job finished successfullyfailed
: Job encountered an error and could not completeaborted
: Job was manually stopped before completionError Responses:
400
: Invalid job_id format401
: Missing API key403
: Invalid API key or job not accessible404
: Job not foundVerify your webhook endpoint is working correctly.
Endpoint: POST /v1/webhook-test
Authentication: None required
Request Body: Any valid JSON
Example Request:
curl -X POST https://api.freshshots.io/v1/webhook-test \
-H "Content-Type: application/json" \
-d '{"test": "data"}'
Response: "✅ Received"
When you provide a webhook_url
when triggering a workflow, FreshShots will send a POST request to your endpoint when the job completes.
Successful Completion:
{
"job_id": 456,
"workflow_id": 123,
"status": "completed",
"processing_time": 42,
"screenshots": [
{
"file_name": "homepage.png",
"url": "https://cdn.freshshots.io/1/homepage.png"
}
],
"timestamp": "2025-01-15T10:30:00Z"
}
Failed Execution:
{
"job_id": 456,
"workflow_id": 123,
"status": "failed",
"error_logs": [
{
"step": 2,
"action": "click_element",
"selector": "submit-button",
"error": "Element not found: data-freshshots-id='submit-button'",
"timestamp": "2025-01-15T10:29:45Z"
}
],
"timestamp": "2025-01-15T10:30:00Z"
}
X-FreshShots-Signature
header for verificationAPI usage is limited based on your subscription plan:
Plan | API Calls per Month | Screenshots per Month |
---|---|---|
Free | Not available | 10 |
Startup ($17/month) | 500 | 500 |
Scaleup ($79/month) | 10,000 | 10,000 |
When you exceed your rate limit, you’ll receive a 429 Too Many Requests
response.
All API errors return a JSON response with details:
{
"error": "Detailed error message",
"code": "ERROR_CODE",
"success": false
}
Invalid API Key:
{
"error": "Invalid or missing API key",
"code": "UNAUTHORIZED"
}
Workflow Not Found:
{
"error": "Workflow not found or access denied",
"code": "NOT_FOUND"
}
Rate Limit Exceeded:
{
"error": "API rate limit exceeded for your plan",
"code": "RATE_LIMIT_EXCEEDED"
}
Invalid Webhook URL:
{
"error": "webhook_url must be a valid HTTPS URL",
"code": "INVALID_WEBHOOK_URL"
}
Basic workflow trigger:
curl -X POST https://api.freshshots.io/v1/run/123 \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json"
Trigger with webhook:
curl -X POST https://api.freshshots.io/v1/run/123 \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"webhook_url": "https://your-app.com/webhook"}'
Check job status:
curl -X GET https://api.freshshots.io/v1/job/456 \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json"
const axios = require('axios');
async function triggerWorkflow(workflow_id, webhookUrl = null) {
try {
const response = await axios.post(
`https://api.freshshots.io/v1/run/${workflow_id}`,
webhookUrl ? { webhook_url: webhookUrl } : {},
{
headers: {
'x-api-key': process.env.FRESHSHOTS_API_KEY,
'Content-Type': 'application/json'
}
}
);
return response.data;
} catch (error) {
console.error('API Error:', error.response.data);
throw error;
}
}
async function checkJobStatus(job_id) {
try {
const response = await axios.get(
`https://api.freshshots.io/v1/job/${job_id}`,
{
headers: {
'x-api-key': process.env.FRESHSHOTS_API_KEY,
'Content-Type': 'application/json'
}
}
);
return response.data;
} catch (error) {
console.error('API Error:', error.response.data);
throw error;
}
}
// Usage
triggerWorkflow(123, 'https://myapp.com/webhook')
.then(result => {
console.log('Job started:', result.job_id);
return checkJobStatus(result.job_id);
})
.then(status => {
console.log('Job status:', status.status);
});
import requests
import os
class FreshShotsAPI:
def __init__(self, api_key):
self.api_key = api_key
self.base_url = "https://api.freshshots.io"
self.headers = {
"x-api-key": api_key,
"Content-Type": "application/json"
}
def trigger_workflow(self, workflow_id, webhook_url=None):
url = f"{self.base_url}/v1/run/{workflow_id}"
data = {}
if webhook_url:
data["webhook_url"] = webhook_url
response = requests.post(url, json=data, headers=self.headers)
response.raise_for_status()
return response.json()
def get_job_status(self, job_id):
url = f"{self.base_url}/v1/job/{job_id}"
response = requests.get(url, headers=self.headers)
response.raise_for_status()
return response.json()
# Usage
api = FreshShotsAPI(os.environ["FRESHSHOTS_API_KEY"])
# Trigger workflow
result = api.trigger_workflow(123, "https://myapp.com/webhook")
print(f"Job started: {result['job_id']}")
# Check status
status = api.get_job_status(result['job_id'])
print(f"Job status: {status['status']}")
For API support, technical issues, or feature requests:
Include your API key prefix (first 8 characters) and relevant error messages when contacting support.
Save time and avoid manual screenshot hassle — keep your docs and helpdesk perfectly up to date with automated, consistent visuals that impress users and cut support requests.
Get started now