API Reference
Integrate Rutt into your workflow. Manage articles, social posts, and webhooks programmatically.
https://aimonitor.io/api/v1
Authentication
All authenticated API requests require an API key. Keys are scoped to your team and can be created in the dashboard. You can authenticate using either method below.
Option 1: Bearer token (recommended)
Pass your key in the Authorization header:
Authorization: Bearer aim_xxxxxxxxxxxx
Option 2: Query parameter
Pass your key as the api_key query parameter:
https://aimonitor.io/api/v1/articles?api_key=aim_xxxxxxxxxxxx
Note: The Bearer header method is preferred as it keeps your key out of URLs, server logs, and browser history.
API keys use the aim_ prefix followed by 48 random characters. Keys that are inactive or expired will return a 401 error.
Permissions
| Permission | Allows |
|---|---|
read |
GET requests only — list and retrieve resources |
read-write |
All methods — create, update, and delete resources |
# Bearer token (recommended)
curl https://aimonitor.io/api/v1/articles \
-H "Authorization: Bearer aim_your_api_key_here"
# Query parameter
curl "https://aimonitor.io/api/v1/articles?api_key=aim_your_api_key_here"
Articles
Create, manage, and retrieve articles. Write operations require a read-write API key.
/v1/articles
Retrieve a paginated list of articles.
Query parameters
| Parameter | Type | Description |
|---|---|---|
status |
string | Filter by status: draft, review, scheduled, published |
site_id |
integer | Filter by site ID |
per_page |
integer | Results per page (default: 15) |
page |
integer | Page number |
Response
{
"data": [
{
"id": 1,
"title": "How to Optimize for AI Search",
"slug": "how-to-optimize-for-ai-search",
"status": "published",
"content_score": 82,
"word_count": 1450,
"published_at": "2026-02-20T14:30:00+00:00",
"created_at": "2026-02-18T09:15:00+00:00"
}
],
"meta": {
"current_page": 1,
"per_page": 15,
"total": 24
}
}
curl "https://aimonitor.io/api/v1/articles?status=published&per_page=10" \
-H "Authorization: Bearer aim_your_api_key_here"
/v1/articles/{id}
Retrieve a single article with full content and SEO fields.
Response
{
"data": {
"id": 1,
"title": "How to Optimize for AI Search",
"slug": "how-to-optimize-for-ai-search",
"status": "published",
"content": "<p>Full HTML content...</p>",
"excerpt": "Learn how to optimize your content...",
"target_keyword": "AI search optimization",
"meta_title": "AI Search Optimization Guide",
"meta_description": "Complete guide to optimizing...",
"content_score": 82,
"word_count": 1450,
"reading_time_minutes": 6,
"featured_image_url": "https://...",
"seo_analysis": { "keyword_density": 1.2 },
"site_id": 5,
"published_at": "2026-02-20T14:30:00+00:00",
"scheduled_at": null,
"created_at": "2026-02-18T09:15:00+00:00",
"updated_at": "2026-02-20T14:30:00+00:00"
}
}
curl https://aimonitor.io/api/v1/articles/1 \
-H "Authorization: Bearer aim_your_api_key_here"
/v1/articles
Create a new article. Requires read-write permission.
Body parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
title |
string | Yes | Article title (max 255 chars) |
content |
string | No | HTML content body |
target_keyword |
string | No | Primary SEO keyword (max 255 chars) |
site_id |
integer | No | Associate with a site |
status |
string | No | draft (default), review, scheduled, published |
Response 201 Created
{
"data": {
"id": 42,
"title": "Getting Started with Rutt",
"slug": "getting-started-with-ai-monitor",
"status": "draft",
"content_score": null,
"word_count": null,
"created_at": "2026-02-26T10:00:00+00:00"
}
}
curl -X POST https://aimonitor.io/api/v1/articles \
-H "Authorization: Bearer aim_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"title": "Getting Started with Rutt",
"content": "Your article content here...
",
"target_keyword": "AI monitor guide",
"status": "draft"
}'
/v1/articles/{id}
Update an existing article. Requires read-write permission. All fields are optional.
Body parameters
| Parameter | Type | Description |
|---|---|---|
title |
string | Article title (max 255 chars) |
content |
string | HTML content body |
target_keyword |
string | Primary SEO keyword |
site_id |
integer | Associate with a site |
status |
string | draft, review, scheduled, published |
curl -X PUT https://aimonitor.io/api/v1/articles/42 \
-H "Authorization: Bearer aim_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{ "status": "published" }'
/v1/articles/{id}
Delete an article. Requires read-write permission.
Response
{
"data": {
"deleted": true
}
}
curl -X DELETE https://aimonitor.io/api/v1/articles/42 \
-H "Authorization: Bearer aim_your_api_key_here"
Webhooks
Webhooks let you receive real-time notifications when events occur in your account. Configure webhook endpoints in the dashboard.
Events
| Event | Description |
|---|---|
article.created |
A new article has been created |
article.published |
An article status changed to published |
article.updated |
An article was modified |
social_post.published |
A social post was successfully published |
social_post.failed |
A social post failed to publish |
Payload format
All webhook payloads follow the same envelope structure:
{
"event": "article.published",
"timestamp": "2026-02-26T14:30:00+00:00",
"data": {
"id": 42,
"title": "How to Optimize for AI Search",
"slug": "how-to-optimize-for-ai-search",
"status": "published",
"published_at": "2026-02-26T14:30:00+00:00"
}
}
Headers
Every webhook request includes these headers:
| Header | Description |
|---|---|
Content-Type |
application/json |
X-Signature |
HMAC-SHA256 signature of the JSON payload |
X-Event |
Event name (e.g. article.published) |
User-Agent |
AIMonitor-Webhook/1.0 |
Verifying signatures
Each webhook endpoint has a unique secret. The X-Signature header contains an HMAC-SHA256 hash of the raw JSON body using your endpoint secret as the key. Always verify signatures to ensure requests are authentic.
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_SIGNATURE'] ?? '';
$secret = 'your_webhook_secret';
$expected = hash_hmac('sha256', $payload, $secret);
if (! hash_equals($expected, $signature)) {
http_response_code(401);
exit('Invalid signature');
}
$event = json_decode($payload, true);
Retries
If your endpoint returns a non-2xx response, we retry up to 3 times with exponential backoff:
| Attempt | Delay |
|---|---|
| 1st retry | 10 seconds |
| 2nd retry | 60 seconds |
| 3rd retry | 5 minutes |
Webhook requests have a 10-second timeout. Respond with a 2xx status within that window to acknowledge receipt.
Rate Limiting
API requests are rate limited per API key to ensure fair usage. Read and write endpoints have separate limits.
| Method | Limit |
|---|---|
Read — GET requests |
120 requests per minute |
Write — POST, PUT, DELETE requests |
30 requests per minute |
Response headers
Rate limit information is included in the response headers:
| Header | Description |
|---|---|
X-RateLimit-Limit |
Max requests allowed in the current window |
X-RateLimit-Remaining |
Requests remaining in the current window |
Retry-After |
Seconds to wait before retrying (only on 429) |
When the rate limit is exceeded, the API returns a 429 Too Many Requests response.
Errors
The API uses standard HTTP status codes to indicate success or failure. Error responses include a JSON body with an error field describing the problem.
| Status | Meaning |
|---|---|
200 |
Success |
201 |
Created |
202 |
Accepted (beacon only) |
401 |
Missing or invalid API key |
403 |
Write permission required (read-only key used for POST/PUT/DELETE) |
404 |
Resource not found |
422 |
Validation failed |
429 |
Rate limit exceeded |
Error response examples
401 Unauthorized
{
"error": "Invalid or expired API key"
}
403 Forbidden
{
"error": "Write permission required"
}
404 Not Found
{
"message": "No query results for model [Article]."
}
422 Validation Error
{
"message": "The title field is required.",
"errors": {
"title": [
"The title field is required."
]
}
}
429 Too Many Requests
{
"message": "Too Many Attempts."
}
Social Posts
Create and manage social media posts. Write operations require a
read-writeAPI key./v1/social-postsRetrieve a paginated list of social posts.
Query parameters
statusdraft,scheduled,published,failedplatformtwitter,linkedin)per_pagepageResponse
/v1/social-posts/{id}Retrieve a single social post with media URLs and engagement data.
Response
/v1/social-postsCreate a new social post. Requires read-write permission.
Body parameters
contentsocial_account_idplatformscheduled_atscheduledResponse 201 Created
/v1/social-posts/{id}Delete a social post. Requires read-write permission.
Response