# ActiveLayer API User Guide

How to retrieve API credentials, which endpoints are available, how payloads should be structured, and what responses to expect.

Updated: Aug 28, 2026
Source: https://activelayer.com/docs/api/
## Overview

The ActiveLayer API takes a piece of content, such as a contact form submission or a comment, and returns a spam verdict with a score. One POST request, answered in milliseconds.

This page covers getting a key, every endpoint, request and response formats, and what each error means.

**Base URL:** `https://api.activelayer.com/api/v1`

**Formats:** JSON request and response payloads

**Versioning:** Current stable version: `v1`

## Quick Start Checklist

- **Generate an API key** — Create an API token in the [ActiveLayer dashboard](https://activelayer.com/) under **API Tokens**.

- **Verify the key** — Call `GET /api/v1/verify` to ensure the token is active before integrating.

- **Send a test request** — Call `POST /api/v1/check` with the cURL snippet below or import the endpoint into Postman.

- **Persist detection IDs** — Log the returned `detection_id` for later audits and feedback submissions.

- **Monitor usage** — Keep an eye on `GET /api/v1/stats` (or your internal metrics) to confirm traffic stays within plan limits.

## Getting an API Key

- Register at [app.activelayer.com/account/register](https://app.activelayer.com/account/register), or sign in at [app.activelayer.com](https://app.activelayer.com/).

- Open your project in the ActiveLayer app. The API key is on the project page; use Regenerate Key there if you need a new one.

- Copy the project API key into a secure server-side secret. Regenerating it invalidates the previous key.

- If the UI does not allow self-service tokens on your plan, contact support or your account manager to provision a key.

## Authentication

- Send `Authorization: Bearer <YOUR_API_KEY>` with every request.

- Compatibility headers include `X-API-Key` or an `api_key` field in the body/query string (discouraged in production).

- All traffic must use HTTPS. Missing, invalid, or revoked keys return `401 Unauthorized`.

## Rate Limiting

API keys are subject to rate limits and plan quotas. The Free plan includes 200 one-time checks; paid plans have a monthly allowance. Exceeding these limits triggers `429 Rate Limit Exceeded` responses with `remaining: 0`.

## Headers & Payload Requirements

Set both headers on every call and send valid JSON payloads:

- `Content-Type: application/json`

- `Accept: application/json`

## POST /api/v1/check

Full spam analysis for longer submissions such as emails, support tickets, or contact forms.

### Request Fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| message | `string` | **Yes** | Text to analyse (email body, form submission, chat message, etc.). |
| email | `string` | No | Sender email address (max 255 characters). |
| name | `string` | No | Author name or nickname. |
| ip | `string` | No | User IPv4/IPv6 address. Defaults to the request IP if omitted. |
| timestamp | `integer` | No | UNIX timestamp for when the content was created. |
| user_agent | `string` | No | Browser or client User-Agent string. |
| website_url | `string (URL)` | No | Source page URL for the submission. |
| domain | `string` | No | Domain associated with the content (helpful for account validation). |

### Sample Request (cURL)

```
curl -X POST "https://api.activelayer.com/api/v1/check" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Hi! I can deliver 1,000 followers for just $5.",
    "email": "offer@example.biz",
    "name": "Cheap Leads Bot",
    "ip": "203.0.113.42",
    "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)",
    "website_url": "https://blog.example.com/contact"
  }'
```

### Sample Response

```
{
  "detection_id": "4b6c9c42-63d6-4eac-9ff7-1965b0dbc1c9",
  "is_spam": true,
  "total_score": 86.4,
  "threshold": 50,
  "execution_time": 121.37,
  "timestamp": "2025-02-15T11:32:18.214Z"
}
```

### Response Fields

| Field | Type | Description |
| --- | --- | --- |
| `detection_id` | `string` | Unique identifier you can reference in audits, feedback, or support tickets. |
| `is_spam` | `boolean` | `true` means the spam threshold was met or exceeded. |
| `total_score` | `float` | Aggregate spam score. Higher values indicate stronger spam signals. |
| `threshold` | `float` | Score required for the detector to classify content as spam. |
| `execution_time` | `float` | Processing time in milliseconds. |
| `timestamp` | `string (ISO 8601)` | Timestamp when the response was generated. |

### PHP Example (Guzzle)

```
<?php
require __DIR__ . '/vendor/autoload.php';
use GuzzleHttp\Client;
$client = new Client([
    'base_uri' => 'https://api.activelayer.com/api/v1/',
    'timeout' => 5.0,
]);
$response = $client->post('check', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('ACTIVELAYER_API_KEY'),
        'Accept' => 'application/json',
    ],
    'json' => [
        'message' => 'Need more traffic? Buy 10k visitors today!',
        'email' => 'sales@spamco.biz',
        'ip' => '198.51.100.87',
    ],
]);
$result = json_decode($response->getBody()->getContents(), true);
if ($result['is_spam']) {
    // Flag the content or block the user here.
}
```

Keep the `detection_id` alongside the original content to support audits or feedback submissions.

## POST /api/v1/check-comment

Optimized for comment or review widgets where you only need a yes/no verdict and a lightweight payload. Accepts the same fields as `/check`.

### Request Fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| message | `string` | **Yes** | Comment or review text to evaluate. |
| email | `string` | No | Commenter email address, if collected. |
| name | `string` | No | Display name or nickname shown publicly. |
| ip | `string` | No | Originating IP address; falls back to the request IP if omitted. |
| timestamp | `integer` | No | UNIX timestamp when the comment was submitted. |
| user_agent | `string` | No | Client or browser user agent string. |

### Sample Request (cURL)

```
curl -X POST "https://api.activelayer.com/api/v1/check-comment" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Great article! Check out my crypto scheme at http://spam.biz",
    "email": "bot@example.biz",
    "ip": "198.51.100.12"
  }'
```

### Sample Response

```
{
  "detection_id": "207e3b47-5f47-42dd-bc0b-775c3e387c33",
  "is_spam": false,
  "total_score": 18.45,
  "threshold": 50,
  "execution_time": 64.09,
  "timestamp": "2025-02-15T11:34:09.817Z"
}
```

### Response Fields

| Field | Type | Description |
| --- | --- | --- |
| `detection_id` | `string` | Identifier to use for logging, audits, or feedback. |
| `is_spam` | `boolean` | Final verdict for the comment payload. |
| `total_score` | `float` | Aggregate score calculated for the comment. |
| `threshold` | `float` | Score threshold used for classification. |
| `execution_time` | `float` | Processing time in milliseconds. |
| `timestamp` | `string (ISO 8601)` | Response generation time. |

Use this endpoint for comments and reviews. It accepts the documented check fields and returns the same verdict fields as /check.

## POST /api/v1/feedback

Submit moderator feedback to improve detection quality.

### Request Fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| detection_id | `string` | **Yes** | Identifier returned by `/check` or `/check-comment`. |
| is_spam | `boolean` | **Yes** | Final label chosen by your system or moderators. |

### Sample Request (cURL)

```
curl -X POST "https://api.activelayer.com/api/v1/feedback" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "detection_id": "4b6c9c42-63d6-4eac-9ff7-1965b0dbc1c9",
    "is_spam": false
  }'
```

### Sample Response

```
{
  "success": true,
  "message": "Feedback submitted and will be processed shortly",
  "data": {
    "detection_id": "4b6c9c42-63d6-4eac-9ff7-1965b0dbc1c9",
    "user_status": true,
    "queued_at": "2025-02-15T11:36:42.055Z"
  }
}
```

### Response Fields

| Field | Type | Description |
| --- | --- | --- |
| `success` | `boolean` | Indicates whether the feedback request was accepted for processing. |
| `message` | `string` | Human-readable confirmation or error message. |
| `data.detection_id` | `string` | Echoes the detection you submitted, so you can correlate the acknowledgement. |
| `data.user_status` | `boolean` | The classification you supplied (`true` for spam, `false` for ham). |
| `data.queued_at` | `string (ISO 8601)` | Server timestamp showing when the feedback job entered the queue. |

Error responses follow the same structure described in [Common Errors](#common-errors) (for example, `404` when a `detection_id` is unknown).

## GET /api/v1/verify

Confirm an API key is active and view metadata about the owner.

### Request Requirements

- **Method:** `GET`

- **Path:** `/api/v1/verify`

- **Headers:** `Authorization: Bearer YOUR_API_KEY`, `Accept: application/json`

- No query parameters or body payload are required.

### Sample Response

```
{
  "valid": true,
  "message": "API key is valid",
  "key_info": {
    "name": "Production key",
    "created_at": "2024-11-19T09:22:11Z",
    "last_used_at": "2025-02-15T11:36:55Z"
  },
  "user_info": {
    "id": 481,
    "email": "ops@example.com",
    "name": "Example Ops"
  },
  "timestamp": "2025-02-15T11:36:55.301Z"
}
```

### Response Fields

| Field | Type | Description |
| --- | --- | --- |
| `valid` | `boolean` | Indicates whether the presented key is active. |
| `message` | `string` | Human-readable summary of the verification result. |
| `key_info.name` | `string` | Friendly label assigned to the API token. |
| `key_info.created_at` | `string (ISO 8601)` | Date and time the token was created. |
| `key_info.last_used_at` | `string (ISO 8601 | null)` | Timestamp of the most recent successful API call using this key. |
| `user_info.id` | `integer` | Internal identifier of the user who owns the key. |
| `user_info.email` | `string` | Contact email associated with the account. |
| `user_info.name` | `string` | Name of the user tied to the key (if provided). |
| `timestamp` | `string (ISO 8601)` | Server timestamp when the verification response was generated. |

## GET /api/v1/stats

Retrieve current plan usage to manage quotas and alerting.

### Request Requirements

- **Method:** `GET`

- **Path:** `/api/v1/stats`

- **Headers:** `Authorization: Bearer YOUR_API_KEY`, `Accept: application/json`

- No body parameters are required; stats are derived from the authenticated account.

### Sample Response

```
{
  "success": true,
  "data": {
    "plan": {
      "name": "Business",
      "id": 3
    },
    "usage": {
      "total_requests": 50000,
      "used_requests": 3125,
      "remaining_requests": 46875,
      "usage_percentage": 6.25
    },
    "period": {
      "month": 2,
      "year": 2025
    }
  },
  "timestamp": "2025-02-15T11:37:12.648Z"
}
```

### Response Fields

| Field | Type | Description |
| --- | --- | --- |
| `success` | `boolean` | Indicates whether the stats lookup succeeded. |
| `data.plan.name` | `string` | Name of the plan associated with the key. |
| `data.plan.id` | `integer` | Internal identifier for the plan. |
| `data.usage.total_requests` | `integer` | Quota for the current period: one-time for Free, monthly for paid plans. |
| `data.usage.used_requests` | `integer` | Requests consumed in the current billing period. |
| `data.usage.remaining_requests` | `integer` | Requests still available before the quota resets. |
| `data.usage.usage_percentage` | `float` | Percentage of the allocated quota already used. |
| `data.period.month` | `integer` | Month the stats snapshot refers to. |
| `data.period.year` | `integer` | Year the stats snapshot refers to. |
| `timestamp` | `string (ISO 8601)` | Server timestamp when the stats were generated. |

## Common Errors

| Status | When it happens | Sample payload |
| --- | --- | --- |
| **401 Unauthorized** | Key missing, invalid, or revoked. | `{"error":"Invalid API key","message":"The provided API key is not valid"}` |
| **403 Forbidden** | User has no active subscription plan. | `{"error":"No Plan","message":"User has no active plan"}` |
| **404 Not Found** | `detection_id` not found during feedback submission. | `{"error":"Detection not found","error_details":"No spam detection found with this detection_id"}` |
| **422 Unprocessable Entity** | Validation rules violated. | `{"error":"Validation failed","errors":{"message":["The message field is required."]}}` |
| **429 Too Many Requests** | Per-minute or monthly quota exceeded. | `{"error":"Rate Limit Exceeded","message":"Monthly request limit exceeded","limit":50000,"used":50000,"remaining":0}` |
| **500 Internal Server Error** | Unexpected server-side exception. | `{"error":"Internal server error","message":"An error occurred while processing your request."}` |

## Testing & Sample Payloads

- **Spam sample:** “Exclusive offer! Buy verified leads now and get 300% ROI. Click here: http://cheap-leads.biz/offer.”

- **Ham sample:** “Hey team, attached is the weekly report. Let me know if you need any follow-up data.”

- Verify keys first with `GET /verify`. Regenerate tokens if you receive `401`.

- Store API keys in environment variables or CI secrets (e.g., `ACTIVELAYER_API_KEY`), never hardcode them.

## Integration Tips

- Persist every `detection_id` with the source content for audits and feedback.

- Retry on `429` with exponential backoff and monitor remaining quotas.

- Add a deployment or runtime health-check that calls `/verify` to ensure credentials remain active.

- Avoid sending unnecessary personal data to minimize compliance risk.

- Use the API reference for currently documented request and response formats.

## Troubleshooting FAQ

### 401 Unauthorized

Confirm the request includes `Authorization: Bearer YOUR_API_KEY` and that the key is still listed under **API Tokens**. Keys are revoked immediately when deleted.

### 403 Forbidden and 429 Too Many Requests

Check `GET /api/v1/stats` for your plan status and remaining quota. Free includes 200 one-time checks that do not reset; upgrade to continue checking. Paid plans have a monthly allowance.

### Need deeper insight into a detection?

Share the `detection_id`, timestamp, and sample payload with support. Logs are indexed by those fields.

### Experiencing high latency?

Send requests from regions close to ActiveLayer infrastructure and consider asynchronous workflows if p95 latency affects user flows.

## Support

- **Technical support:** [support@activelayer.com](mailto:support@activelayer.com)

- **Plan changes:** use the ActiveLayer dashboard. For billing questions, contact the [support team](https://activelayer.com/contact/).
