BotzLy provides a RESTful JSON API to manage campaigns, track clicks, handle conversions, and more.
Base URL: https://yourdomain.com/api
All requests and responses use JSON format. Include the Content-Type: application/json header in your requests.
The full OpenAPI specification is available at /api/openapi.
Most endpoints require a Bearer token. Obtain one via the sign-in endpoint, then include it in all subsequent requests:
Authorization: Bearer YOUR_TOKEN
Tokens are valid for 30 days after creation.
Authenticate and receive an API token.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
email |
string | Yes | Email address |
password |
string | Yes | Password |
Example request:
curl -X POST https://yourdomain.com/api/sign-in \
-H "Content-Type: application/json" \
-d '{"email": "admin@example.com", "password": "password"}'
Response (200):
{
"token": "vW4sIvFvqkw6iogdhNyyFXa2nKg4LlsVobOTR721hbs",
"token_type": "bearer"
}
Create a new user account.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Full name |
email |
string | Yes | Email address |
password |
string | Yes | Password |
avatar |
string | No | Avatar URL |
Example request:
curl -X POST https://yourdomain.com/api/register \
-H "Content-Type: application/json" \
-d '{"name": "John Smith", "email": "john@example.com", "password": "neat_password"}'
Response (200):
{
"token": "abc123def456...",
"token_type": "bearer"
}
Resend confirmation instructions to an existing user.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
email |
string | Yes | Email of existing user |
Example request:
curl -X POST https://yourdomain.com/api/send-instructions \
-H "Content-Type: application/json" \
-d '{"email": "admin@example.com"}'
Response (200):
{
"message": "If the email is in our system, you will receive instructions shortly."
}
These endpoints require authentication.
Retrieve a user profile. You can only access your own profile.
Example request:
curl https://yourdomain.com/api/user/1 \
-H "Authorization: Bearer YOUR_TOKEN"
Response (200):
{
"id": 1,
"name": "John Smith",
"email": "admin@example.com",
"is_confirmed": true,
"is_admin": true,
"role": "admin",
"avatar": "",
"is_suspended": false,
"is_deleted": false,
"is_onboarded": true
}
Update your profile information.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | No | New name |
avatar |
string | No | New avatar URL |
Example request:
curl -X PATCH https://yourdomain.com/api/user/1/update \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Jane Smith", "avatar": "https://example.com/avatar.jpg"}'
Response (200): Returns the updated user object.
Request to change your email address. A confirmation email will be sent to the new address.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
requested_email |
string | Yes | New email address |
Example request:
curl -X POST https://yourdomain.com/api/user/1/request-new-email \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"requested_email": "newemail@example.com"}'
Response (200):
{
"message": "An email was sent to your new address. Please check your inbox."
}
Change your password.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
current_password |
string | Yes | Current password |
password |
string | Yes | New password |
password_confirmation |
string | Yes | Confirm new password |
Example request:
curl -X POST https://yourdomain.com/api/user/1/change-password \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"current_password": "old_pass", "password": "new_pass", "password_confirmation": "new_pass"}'
Response (200):
{
"message": "Password changed successfully."
}
All v1 endpoints are scoped to an organization and require authentication. They also have rate limiting applied.
Base path: /api/v1/org/:org_slug
Replace :org_slug with your organization’s slug (e.g., my-agency).
List all campaigns for the organization, with pagination and optional status filter.
Query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
page |
integer | 1 | Page number |
page_size |
integer | 25 | Items per page (max 100) |
status |
string | — |
Filter by status: active, draft, paused, completed, inactive |
Example request:
curl "https://yourdomain.com/api/v1/org/my-agency/campaigns?page=1&page_size=10&status=active" \
-H "Authorization: Bearer YOUR_TOKEN"
Response (200):
{
"data": [
{
"id": 1,
"name": "Summer Sale 2024",
"description": "Promotional campaign for summer products",
"status": "active",
"starts_at": "2024-06-01T00:00:00Z",
"ends_at": "2024-08-31T23:59:59Z",
"landing_url": "https://example.com/summer-sale",
"preview_url": null,
"allowed_countries": ["FR", "BE"],
"advertiser": {
"id": 1,
"name": "John Doe",
"company_name": "Acme Corp",
"status": "active"
},
"inserted_at": "2024-05-15T10:30:00Z",
"updated_at": "2024-05-20T14:45:00Z"
}
],
"meta": {
"total": 42,
"page": 1,
"page_size": 10
}
}
Retrieve a single campaign by ID, including its associated advertiser.
Example request:
curl https://yourdomain.com/api/v1/org/my-agency/campaigns/1 \
-H "Authorization: Bearer YOUR_TOKEN"
Response (200):
{
"data": {
"id": 1,
"name": "Summer Sale 2024",
"description": "Promotional campaign for summer products",
"status": "active",
"starts_at": "2024-06-01T00:00:00Z",
"ends_at": "2024-08-31T23:59:59Z",
"landing_url": "https://example.com/summer-sale",
"preview_url": "https://example.com/preview/summer-sale",
"allowed_countries": ["FR", "BE", "CH"],
"advertiser": {
"id": 1,
"name": "John Doe",
"company_name": "Acme Corp",
"status": "active"
},
"inserted_at": "2024-05-15T10:30:00Z",
"updated_at": "2024-05-20T14:45:00Z"
}
}
Get aggregated statistics for a campaign (clicks, conversions, revenue, payout).
Query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
start_date |
string | — | Start date filter (ISO 8601) |
end_date |
string | — | End date filter (ISO 8601) |
affiliate_id |
string | — | Filter stats by specific affiliate |
Example request:
curl "https://yourdomain.com/api/v1/org/my-agency/campaigns/1/stats?start_date=2024-06-01&end_date=2024-06-30" \
-H "Authorization: Bearer YOUR_TOKEN"
Response (200):
{
"data": {
"impressions": 10000,
"clicks": 500,
"conversions": 25,
"conversion_rate": 5.0,
"revenue": "2500.00",
"payout": "1250.00"
}
}
List tracked clicks with pagination and filters.
Query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
page |
integer | 1 | Page number |
page_size |
integer | 25 | Items per page (max 100) |
status |
string | — |
Filter by status: approved, pending, rejected |
campaign_id |
string | — | Filter by campaign ID |
affiliate_id |
string | — | Filter by affiliate ID |
start_date |
string | — | Start date filter (ISO 8601) |
end_date |
string | — | End date filter (ISO 8601) |
Example request:
curl "https://yourdomain.com/api/v1/org/my-agency/clicks?status=approved&campaign_id=1&page=1" \
-H "Authorization: Bearer YOUR_TOKEN"
Response (200):
{
"data": [
{
"click_id": "d4e5f6a7-b8c9-0123-def1-234567890123",
"organization_id": "org-uuid",
"campaign_id": "1",
"affiliate_id": "42",
"remuneration_id": "5",
"tracked_link_id": "7",
"timestamp": "2024-06-15T14:30:00Z",
"ip_address": "192.168.1.1",
"user_agent": "Mozilla/5.0...",
"referer": "https://affiliate-site.com",
"revenue": 0.50,
"payout": 0.25,
"status": "approved",
"rejection_reason": null
}
],
"meta": {
"total": 1250,
"page": 1,
"page_size": 25
}
}
List conversions with pagination and filters.
Query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
page |
integer | 1 | Page number |
page_size |
integer | 25 | Items per page (max 100) |
status |
string | — |
Filter by status: approved, pending, rejected |
campaign_id |
string | — | Filter by campaign ID |
affiliate_id |
string | — | Filter by affiliate ID |
start_date |
string | — | Start date filter (ISO 8601) |
end_date |
string | — | End date filter (ISO 8601) |
Example request:
curl "https://yourdomain.com/api/v1/org/my-agency/conversions?status=pending&page=1" \
-H "Authorization: Bearer YOUR_TOKEN"
Response (200):
{
"data": [
{
"click_id": "d4e5f6a7-b8c9-0123-def1-234567890123",
"organization_id": "org-uuid",
"campaign_id": "1",
"affiliate_id": "42",
"remuneration_id": "5",
"tracked_link_id": "7",
"timestamp": "2024-06-15T15:00:00Z",
"ip_address": "192.168.1.1",
"user_agent": "Mozilla/5.0...",
"revenue": 50.00,
"payout": 25.00,
"status": "pending",
"rejection_reason": null
}
],
"meta": {
"total": 150,
"page": 1,
"page_size": 25
}
}
Approve a pending conversion. The :id parameter is the click_id.
Example request:
curl -X POST https://yourdomain.com/api/v1/org/my-agency/conversions/d4e5f6a7-b8c9-0123-def1-234567890123/approve \
-H "Authorization: Bearer YOUR_TOKEN"
Response (200):
{
"status": "approved",
"click_id": "d4e5f6a7-b8c9-0123-def1-234567890123"
}
Reject a pending conversion. The :id parameter is the click_id.
Request body (optional):
| Field | Type | Required | Description |
|---|---|---|---|
reason |
string | No | Reason for rejection |
Example request:
curl -X POST https://yourdomain.com/api/v1/org/my-agency/conversions/d4e5f6a7-b8c9-0123-def1-234567890123/reject \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"reason": "Suspected fraud"}'
Response (200):
{
"status": "rejected",
"click_id": "d4e5f6a7-b8c9-0123-def1-234567890123"
}
List all logs for a specific postback. The :id parameter is the postback UUID.
Example request:
curl https://yourdomain.com/api/v1/org/my-agency/postbacks/b2c3d4e5-f6a7-8901-bcde-f12345678901/logs \
-H "Authorization: Bearer YOUR_TOKEN"
Response (200):
{
"data": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"postback_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"conversion_id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"click_id": "d4e5f6a7-b8c9-0123-def1-234567890123",
"event_type": "conversion",
"url_sent": "https://affiliate.com/postback?click_id=abc123&status=approved",
"http_status": 200,
"response_body": "OK",
"success": true,
"error_message": null,
"attempt_number": 1,
"inserted_at": "2024-05-20T15:30:00Z"
}
]
}
All list endpoints return paginated results with the following structure:
{
"data": [...],
"meta": {
"total": 42,
"page": 1,
"page_size": 25
}
}
Use the page and page_size query parameters to navigate through results. Maximum page_size is 100.
The API uses standard HTTP status codes:
| Code | Description |
|---|---|
| 200 | Success |
| 401 | Unauthorized — missing or invalid token |
| 403 | Forbidden — you don’t have access to this resource |
| 404 | Not Found — the resource doesn’t exist |
| 422 | Unprocessable Entity — validation errors in your request |
| 429 | Too Many Requests — rate limit exceeded |
Error response format:
{
"error": "Description of what went wrong"
}
Validation error response (422):
{
"errors": {
"email": ["can't be blank"],
"password": ["should be at least 8 characters"]
}
}
API v1 organization endpoints (/api/v1/org/...) are rate limited to prevent abuse. If you exceed the limit, you’ll receive a 429 Too Many Requests response. Wait before retrying.
/api/openapi We use cookies for analytics and to improve your experience. Privacy policy.