Schedule Endpoints
Create and manage automated, recurring scrapes via HTTP.
Create schedule
Create a new recurring schedule.
Request body (interval-based)
{
"strategy_id": "550e8400-e29b-41d4-a716-446655440000",
"url": "https://example.com/products",
"interval_seconds": 3600,
"webhook_url": "https://your-app.com/webhooks/meter"
}
Request body (cron-based)
{
"strategy_id": "550e8400-e29b-41d4-a716-446655440000",
"url": "https://example.com/products",
"cron_expression": "0 9 * * *",
"webhook_url": "https://your-app.com/webhooks/meter"
}
| Field | Type | Required | Description |
|---|
strategy_id | string | Yes | Strategy UUID |
url | string | Conditional | Single URL to scrape (use url OR urls, not both) |
urls | array | Conditional | List of URLs to scrape (use url OR urls, not both) |
interval_seconds | integer | Conditional | Interval in seconds (minimum: 60) |
cron_expression | string | Conditional | Cron expression |
webhook_url | string | No | Webhook URL for notifications |
webhook_metadata | object | No | Custom JSON metadata included in every webhook payload |
webhook_secret | string | No | Secret for X-Webhook-Secret header. Auto-generated if not provided when webhook_url is set |
webhook_type | string | No | standard or slack. Auto-detected from URL if not specified |
parameters | object | No | Default API parameter overrides for all scheduled runs (API strategies only) |
Provide either interval_seconds or cron_expression, not both. Provide either url or urls, not both.
Response
{
"schedule_id": "880e8400-e29b-41d4-a716-446655440000",
"strategy_id": "550e8400-e29b-41d4-a716-446655440000",
"url": "https://example.com/products",
"urls": null,
"schedule_type": "interval",
"interval_seconds": 3600,
"cron_expression": null,
"enabled": true,
"webhook_url": "https://your-app.com/webhooks/meter",
"webhook_metadata": null,
"webhook_secret": "whsec_a1b2c3...",
"webhook_type": "standard",
"parameters": null,
"next_run_at": "2025-01-15T11:30:00Z",
"last_run_at": null,
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}
The webhook_secret is only returned in the create response. It is not included in subsequent GET responses.
### Example
```bash
# Interval-based
curl -X POST https://api.meter.sh/api/schedules \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"strategy_id": "550e8400-e29b-41d4-a716-446655440000",
"url": "https://example.com/products",
"interval_seconds": 3600
}'
# Cron-based
curl -X POST https://api.meter.sh/api/schedules \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"strategy_id": "550e8400-e29b-41d4-a716-446655440000",
"url": "https://example.com/products",
"cron_expression": "0 9 * * *"
}'
List schedules
Get all schedules for the authenticated user.
Response
Array of schedule objects (same format as Create schedule response).
Example
curl https://api.meter.sh/api/schedules \
-H "Authorization: Bearer sk_live_..."
Update schedule
Update an existing schedule.
PATCH /api/schedules/{schedule_id}
Request body
All fields are optional. Include only fields to update:
{
"enabled": false,
"interval_seconds": 7200,
"webhook_url": "https://new-domain.com/webhooks",
"webhook_metadata": {"project": "updated-project"},
"webhook_type": "standard"
}
| Field | Type | Description |
|---|
enabled | boolean | Enable/disable the schedule |
url | string | Update to a single URL |
urls | array | Update to multiple URLs |
interval_seconds | integer | New interval in seconds |
cron_expression | string | New cron expression |
webhook_url | string | New webhook URL (or null to remove) |
webhook_metadata | object | Update custom JSON metadata for webhook payloads |
webhook_secret | string | Update webhook secret |
webhook_type | string | Update webhook type: standard or slack |
parameters | object | Update API parameter defaults |
Response
Updated schedule object.
Example
# Disable schedule
curl -X PATCH https://api.meter.sh/api/schedules/880e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{"enabled": false}'
# Change interval
curl -X PATCH https://api.meter.sh/api/schedules/880e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{"interval_seconds": 7200}'
Delete schedule
Delete a schedule (stops future jobs).
DELETE /api/schedules/{schedule_id}
Response
{
"message": "Schedule deleted successfully"
}
Example
curl -X DELETE https://api.meter.sh/api/schedules/880e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer sk_live_..."
Regenerate webhook secret
Generate a new webhook secret for a schedule. The old secret is immediately invalidated.
POST /api/schedules/{schedule_id}/webhook-secret/regenerate
Response
{
"schedule_id": "880e8400-e29b-41d4-a716-446655440000",
"webhook_secret": "whsec_new_secret_here..."
}
The new secret is returned only once. Store it securely and update your webhook handler before the next delivery.
Example
curl -X POST https://api.meter.sh/api/schedules/880e8400-e29b-41d4-a716-446655440000/webhook-secret/regenerate \
-H "Authorization: Bearer sk_live_..."
Get schedule changes
Get unseen changes for a schedule (pull-based change detection).
GET /api/schedules/{schedule_id}/changes?mark_seen=true&filter=+keyword
Query parameters
| Parameter | Type | Required | Description |
|---|
mark_seen | boolean | No | Mark changes as seen (default: true) |
filter | string | No | Lucene-style keyword filter for result items |
Keyword filter syntax
The filter parameter uses Lucene-style syntax to filter individual result items:
| Syntax | Meaning | Example |
|---|
+keyword | Required (AND) | +rubio +tariff - items with both |
keyword | Optional (OR) | rubio elon - items with either |
-keyword | Excluded (NOT) | -bitcoin - items without |
"phrase" | Exact phrase | "elon musk" - exact match |
The filter applies to individual items within results, not entire jobs.
Jobs with zero matching items are excluded from the response.
Response
{
"schedule_id": "880e8400-e29b-41d4-a716-446655440000",
"changes": [
{
"job_id": "660e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"results": [...],
"item_count": 12,
"content_hash": "7f3d9a2b4c1e...",
"completed_at": "2025-01-15T10:30:12Z",
"seen": true
}
],
"count": 1,
"marked_seen": true,
"filter_applied": "+rubio +tariff"
}
Example
# Get and mark as seen
curl https://api.meter.sh/api/schedules/880e8400-e29b-41d4-a716-446655440000/changes \
-H "Authorization: Bearer sk_live_..."
# Preview without marking
curl https://api.meter.sh/api/schedules/880e8400-e29b-41d4-a716-446655440000/changes?mark_seen=false \
-H "Authorization: Bearer sk_live_..."
# Filter for items containing both "rubio" AND "tariff"
curl "https://api.meter.sh/api/schedules/880e8400-e29b-41d4-a716-446655440000/changes?filter=%2Brubio+%2Btariff" \
-H "Authorization: Bearer sk_live_..."
# Filter for items containing "rubio" OR "elon"
curl "https://api.meter.sh/api/schedules/880e8400-e29b-41d4-a716-446655440000/changes?filter=rubio+elon" \
-H "Authorization: Bearer sk_live_..."
# Filter for items with "rubio" but NOT "biden"
curl "https://api.meter.sh/api/schedules/880e8400-e29b-41d4-a716-446655440000/changes?filter=%2Brubio+-biden" \
-H "Authorization: Bearer sk_live_..."
Webhook payload
When a schedule has a webhook URL, Meter POSTs to it after each job:
{
"job_id": "660e8400-e29b-41d4-a716-446655440000",
"schedule_id": "880e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"results": [...],
"item_count": 12,
"has_changes": true,
"content_hash": "7f3d9a2b4c1e...",
"completed_at": "2025-01-15T10:30:12Z"
}
See the Webhooks Guide for implementation details.
Error responses
| Status | Description |
|---|
400 | Invalid request (invalid cron expression, missing required fields) |
401 | Invalid or missing API key |
404 | Schedule or strategy not found |
500 | Internal server error |
503 | Service temporarily unavailable |
See REST API Errors for detailed error handling.
Next steps
Need help?
Email me at mckinnon@meter.sh