Scampilot API Documentation

Complete REST API for AI-powered scam detection and prevention

v1.0.0

Introduction

Welcome to the Scampilot API documentation. This API provides programmatic access to our AI-powered scam detection and prevention platform.

Base URLs

Environment URL
Production https://scampilot.de/api
Development https://scampilot.test/api

Features

  • AI Checks: Submit text, links, images, or emails for scam analysis
  • Questionnaires: Interactive risk assessment questionnaires
  • Usage Tracking: Monitor API usage and limits
  • Plan Management: Access subscription plan information

Authentication

Most endpoints require Bearer token authentication using Laravel Sanctum.

Creating an API Token

  1. Log in to your Scampilot account
  2. Navigate to Developer Portal → API Tokens at /developer/tokens
  3. Click Create API Token
  4. Enter a name for the token and select permissions
  5. Copy the generated token (shown only once)

Using Your Token

Include the token in the Authorization header of your requests:

Authorization: Bearer YOUR_API_TOKEN_HERE
Accept: application/json

Example Request

curl -X GET https://scampilot.de/api/user \
  -H "Authorization: Bearer 1|abc123def456..." \
  -H "Accept: application/json"

Security Note

Never commit tokens to version control. Use environment variables and rotate tokens regularly.

Rate Limiting

API requests are rate limited to prevent abuse.

User Type Rate Limit
Authenticated Users 60 requests per minute
Anonymous Users 10 requests per minute

Rate Limit Headers

Response includes rate limit information:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
X-RateLimit-Reset: 1633024800

Rate Limit Exceeded (429)

{
  "message": "Too Many Attempts.",
  "retry_after": 60
}

Error Handling

HTTP Status Codes

Code Description
200Success
201Created
204No Content
400Bad Request
401Unauthorized
403Forbidden
404Not Found
422Validation Error
429Too Many Requests
500Server Error

Error Response Format

{
  "message": "The given data was invalid.",
  "errors": {
    "email": [
      "The email field is required."
    ]
  }
}

User

GET /api/user

Retrieve the currently authenticated user's information.

Headers

Authorization: Bearer {token}
Accept: application/json

Response (200 OK)

{
  "id": 1,
  "name": "John Doe",
  "email": "john@example.com",
  "email_verified_at": "2025-10-09T12:00:00.000000Z",
  "profile_photo_url": "https://...",
  "created_at": "2025-10-09T10:00:00.000000Z",
  "updated_at": "2025-10-09T11:00:00.000000Z"
}

Plans

GET /api/plans

Get all active subscription plans. No authentication required.

Response (200 OK)

{
  "plans": [
    {
      "id": 1,
      "name": "free",
      "display_name": "Kostenlos",
      "description": "Perfekt zum Ausprobieren",
      "price_monthly": "0.00",
      "price_yearly": "0.00",
      "checks_per_day": 5,
      "unlimited_checks": false,
      "features": [
        "5 Prüfungen pro Tag",
        "Zugang zu Basis-Kursen"
      ]
    }
  ]
}
GET /api/plans/current

Get the authenticated user's current subscription plan and usage.

Response (200 OK)

{
  "plan": {
    "name": "pro",
    "display_name": "Scampilot Pro"
  },
  "usage": {
    "today": 15,
    "this_month": 342
  },
  "remaining": null,
  "subscription": {
    "is_subscribed": true,
    "on_trial": false
  }
}

AI Checks

POST /api/checks

Submit content for AI-powered scam analysis. Supports text, links, images, and emails.

Asynchronous Processing

Analysis is performed asynchronously. Use the status endpoint to poll for results.

Request Body (Text/Email)

{
  "type": "text",
  "content": "URGENT: Your bank account will be closed!..."
}

Request Body (Link)

{
  "type": "link",
  "url": "https://suspicious-site.com",
  "content": "Optional context"
}

Response (201 Created)

{
  "message": "Prüfung erstellt und wird analysiert",
  "check": {
    "uuid": "123e4567-e89b-12d3-a456-426614174000",
    "type": "text",
    "webhook_status": "processing"
  },
  "status": "processing"
}
GET /api/checks/{uuid}/status

Check the current status of an AI analysis.

Response (200 OK)

{
  "uuid": "123e4567-e89b-12d3-a456-426614174000",
  "status": "completed",
  "risk_level": "warning",
  "is_complete": true,
  "is_pending": false,
  "has_failed": false
}
GET /api/checks/{uuid}

Retrieve full details of a completed check.

Response (200 OK)

{
  "uuid": "123e4567-e89b-12d3-a456-426614174000",
  "type": "text",
  "risk_level": "warning",
  "risk_score": 65,
  "ai_explanation": "Diese Nachricht enthält...",
  "ai_indicators": [
    "Ungewöhnliche Dringlichkeit",
    "Verdächtige Links"
  ],
  "risk_text": "Vorsicht",
  "risk_color": "yellow"
}

Usage Tracking

GET /api/usage

Get current usage statistics. Works for both authenticated and anonymous users.

Response (200 OK)

{
  "usage": {
    "today": 3,
    "this_month": 45,
    "all_time": 312
  },
  "remaining": 2,
  "limit": 5,
  "is_unlimited": false,
  "plan": {
    "name": "free",
    "display_name": "Kostenlos"
  }
}
GET /api/usage/can-perform/{feature}

Check if user can perform a specific action based on limits.

Response (200 OK)

{
  "can_perform": true,
  "remaining": 2,
  "limit": 5,
  "is_unlimited": false
}

Questionnaires

GET /api/questionnaires

Get all active questionnaires.

Response (200 OK)

{
  "questionnaires": [
    {
      "slug": "phishing-verdacht",
      "title": "Phishing-Verdacht prüfen",
      "category": "phishing",
      "estimated_duration": 3
    }
  ]
}
POST /api/questionnaires/{slug}/start

Begin a new questionnaire session.

Response (201 Created)

{
  "message": "Fragebogen gestartet",
  "response": {
    "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "started_at": "2025-10-09T20:30:00.000000Z"
  }
}

Webhooks

POST /api/webhooks/ai-check/{uuid}

Endpoint for n8n to send AI analysis results.

Request Body

{
  "risk_level": "warning",
  "risk_score": 65,
  "explanation": "Diese Nachricht zeigt...",
  "indicators": ["Dringlichkeit", "Verdächtige Links"]
}

Code Examples

JavaScript
Python
PHP
cURL
// Create an AI check
const response = await fetch('https://scampilot.de/api/checks', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  },
  body: JSON.stringify({
    type: 'text',
    content: 'Suspicious message content...'
  })
});

const data = await response.json();
const checkUuid = data.check.uuid;

// Poll for results
async function pollForResults(uuid) {
  const statusRes = await fetch(
    `https://scampilot.de/api/checks/${uuid}/status`
  );
  const status = await statusRes.json();
  
  if (status.is_complete) {
    const resultsRes = await fetch(
      `https://scampilot.de/api/checks/${uuid}`
    );
    return await resultsRes.json();
  }
  
  // Wait 2 seconds and try again
  await new Promise(resolve => setTimeout(resolve, 2000));
  return pollForResults(uuid);
}

const results = await pollForResults(checkUuid);
console.log('Risk Level:', results.risk_level);
console.log('Explanation:', results.ai_explanation);
import requests
import time

# Create an AI check
response = requests.post(
    'https://scampilot.de/api/checks',
    json={
        'type': 'text',
        'content': 'Suspicious message content...'
    }
)

check_uuid = response.json()['check']['uuid']

# Poll for results
def poll_for_results(uuid):
    while True:
        status_res = requests.get(
            f'https://scampilot.de/api/checks/{uuid}/status'
        )
        status = status_res.json()
        
        if status['is_complete']:
            results_res = requests.get(
                f'https://scampilot.de/api/checks/{uuid}'
            )
            return results_res.json()
        
        time.sleep(2)

results = poll_for_results(check_uuid)
print(f"Risk Level: {results['risk_level']}")
print(f"Explanation: {results['ai_explanation']}")
 'text',
    'content' => 'Suspicious message content...'
]);

$checkUuid = $response->json()['check']['uuid'];

// Poll for results
function pollForResults($uuid) {
    while (true) {
        $statusRes = Http::get(
            "https://scampilot.de/api/checks/{$uuid}/status"
        );
        $status = $statusRes->json();
        
        if ($status['is_complete']) {
            $resultsRes = Http::get(
                "https://scampilot.de/api/checks/{$uuid}"
            );
            return $resultsRes->json();
        }
        
        sleep(2);
    }
}

$results = pollForResults($checkUuid);
echo "Risk Level: " . $results['risk_level'] . "\n";
echo "Explanation: " . $results['ai_explanation'] . "\n";
# Create an AI check
curl -X POST https://scampilot.de/api/checks \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "type": "text",
    "content": "Suspicious message content..."
  }'

# Check status
curl https://scampilot.de/api/checks/{uuid}/status

# Get full results
curl https://scampilot.de/api/checks/{uuid}