API Documentation

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.


Authentication

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.


POST /api/sign-in

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"
}

POST /api/register

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"
}

POST /api/send-instructions

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."
}

Profile Management

These endpoints require authentication.


GET /api/user/:id

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
}

PATCH /api/user/:id/update

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.


POST /api/user/:id/request-new-email

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."
}

POST /api/user/:id/change-password

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."
}

API v1 β€” Organization Endpoints

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).


Campaigns

GET /api/v1/org/:org_slug/campaigns

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
  }
}

GET /api/v1/org/:org_slug/campaigns/:id

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 /api/v1/org/:org_slug/campaigns/:id/stats

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"
  }
}

Clicks

GET /api/v1/org/:org_slug/clicks

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
  }
}

Conversions

GET /api/v1/org/:org_slug/conversions

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
  }
}

POST /api/v1/org/:org_slug/conversions/:id/approve

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"
}

POST /api/v1/org/:org_slug/conversions/:id/reject

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"
}

Postback Logs

GET /api/v1/org/:org_slug/postbacks/:id/logs

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"
    }
  ]
}

Pagination

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.


Error Handling

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"]
  }
}

Rate Limiting

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.


Need Help?

We use cookies for analytics and to improve your experience. Privacy policy.