Skip to content

API

Overview

Botble CMS includes a REST API package that lets you interact with your application data from mobile apps, third-party services, or any HTTP client. It uses Laravel Sanctum for token-based authentication and supports optional API key protection, push notifications via Firebase Cloud Messaging (FCM), and user settings management.

The API is managed at Admin > Settings > API (/admin/settings/api).

API Settings

Enabling the API

Go to Admin > Settings > API and toggle Enable API. When disabled, all /api/v1/* endpoints return 503 Service Unavailable.

API Key Protection

API key protection adds a second layer of security on top of Sanctum tokens. When enabled, every request must include an X-API-KEY header.

  1. In Admin > Settings > API, enable API Key Protection.
  2. Copy the generated key (or click Generate to create a new one).
  3. Add the header to all requests:
bash
curl -X GET https://your-domain.com/api/v1/posts \
  -H "Authorization: Bearer your-sanctum-token" \
  -H "X-API-KEY: your-api-key" \
  -H "Content-Type: application/json"

Without a valid key, the API returns 401 Unauthorized:

json
{
  "message": "Invalid or missing API key. Please provide a valid X-API-KEY header.",
  "error": "Unauthorized"
}

TIP

Think of the API key as a gate key for your entire app, while the Sanctum token identifies individual users. The API key prevents unauthorized clients from accessing the API at all; the Sanctum token controls what each user can do.

Common use cases:

  • Restrict API access to only your official mobile app
  • Revoke all access instantly by rotating the key, without invalidating user sessions
  • Add a layer of protection against scrapers or unauthorized integrations

Sanctum Token Management

Admins can create and manage server-side API tokens at Admin > Settings > API > API Tokens. These tokens are useful for server-to-server integration (e.g., syncing data from an ERP).

  • Click Create to generate a named token. The plain-text token is shown only once — copy it immediately.
  • Tokens can be deleted individually from the table.

Authentication

Login

bash
POST /api/v1/login
Content-Type: application/json

{
  "email": "[email protected]",
  "password": "your-password"
}

Response:

json
{
  "error": false,
  "data": {
    "token": "1|abc123...",
    "user": {
      "id": 1,
      "name": "John Doe",
      "email": "[email protected]"
    }
  },
  "message": null
}

Register

bash
POST /api/v1/register
Content-Type: application/json

{
  "first_name": "John",
  "last_name": "Doe",
  "email": "[email protected]",
  "password": "secret123",
  "password_confirmation": "secret123",
  "phone": "+1234567890"
}

Using the Token

Include the token in the Authorization header for all authenticated requests:

bash
curl -X GET https://your-domain.com/api/v1/me \
  -H "Authorization: Bearer 1|abc123..." \
  -H "Content-Type: application/json"

Logout

bash
GET /api/v1/logout
Authorization: Bearer your-token

This revokes all tokens for the authenticated user.

Password Reset

bash
# Request reset link
POST /api/v1/password/forgot
{ "email": "[email protected]" }

# Reset password (using token from email)
POST /api/v1/password/reset
{ "email": "[email protected]", "token": "reset-token", "password": "new-password", "password_confirmation": "new-password" }

Email Verification

If email verification is enabled in the API config, unverified users can request a new verification email:

bash
POST /api/v1/resend-verify-account-email
{ "email": "[email protected]" }

Available Endpoints

Authentication (Public)

MethodEndpointDescription
POST/api/v1/registerRegister new user
POST/api/v1/loginLogin and get token
POST/api/v1/email/checkCheck if email exists
POST/api/v1/password/forgotSend password reset link
POST/api/v1/resend-verify-account-emailResend verification email
POST/api/v1/device-tokensRegister device token

Profile (Authenticated)

MethodEndpointDescription
GET/api/v1/meGet user profile
PUT/api/v1/meUpdate profile (name, email, phone, DOB, gender)
POST/api/v1/update/avatarUpload user avatar
PUT/api/v1/update/passwordChange password (requires current password)
GET/api/v1/logoutLogout and revoke tokens

User Settings (Authenticated)

MethodEndpointDescription
GET/api/v1/settingsGet user settings
PUT/api/v1/settingsUpdate user settings

Available settings:

KeyTypeDefaultDescription
biometric_enabledbooleanfalseEnable biometric authentication
notification_enabledbooleantrueEnable push notifications
languagestringenPreferred language
currencystringUSDPreferred currency
themestringlightTheme preference (light, dark, auto)
timezonestringUTCUser timezone

Device Tokens (Authenticated)

MethodEndpointDescription
POST/api/v1/device-tokensRegister or update a device token
GET/api/v1/device-tokensList user's active device tokens
PUT/api/v1/device-tokens/{id}Update device token metadata
DELETE/api/v1/device-tokens/{id}Delete device token
DELETE/api/v1/device-tokens/by-tokenDelete by token value
POST/api/v1/device-tokens/{id}/deactivateDeactivate without deleting

Notifications (Authenticated)

MethodEndpointDescription
GET/api/v1/notificationsList notifications (paginated)
GET/api/v1/notifications/statsGet notification statistics
POST/api/v1/notifications/mark-all-readMark all as read
POST/api/v1/notifications/{id}/readMark one as read
POST/api/v1/notifications/{id}/clickedMark as clicked
DELETE/api/v1/notifications/{id}Delete notification

Query parameters for listing:

ParameterDescription
pagePage number
per_pageItems per page (max 50)
unread_onlyOnly return unread notifications
typeFilter by type (general, order, promotion, system)

Blog Endpoints

MethodEndpointDescription
GET/api/v1/postsList blog posts
GET/api/v1/posts/{id}Get a blog post
GET/api/v1/categoriesList blog categories
GET/api/v1/categories/{id}Get a blog category
GET/api/v1/tagsList blog tags
GET/api/v1/tags/{id}Get a blog tag

Page Endpoints

MethodEndpointDescription
GET/api/v1/pagesList pages
GET/api/v1/pages/{id}Get a page

Plugin Endpoints

Depending on installed plugins, additional endpoints may be available for:

  • E-commerce (products, orders, customers, carts, wishlists)
  • Galleries
  • Contact forms
  • And more

Request Parameters

Pagination

GET /api/v1/posts?page=2&per_page=15
  • page — Page number (default: 1)
  • per_page — Items per page (default: 10, max: 100)

Filtering

GET /api/v1/posts?status=published&category_id=5

Sorting

GET /api/v1/posts?sort_by=created_at&order=desc

Including Relations

GET /api/v1/posts?include=categories,tags,author

Response Format

Success (single resource)

json
{
  "error": false,
  "data": {
    "id": 1,
    "name": "Example"
  },
  "message": null
}

Success (paginated)

json
{
  "data": [...],
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 5,
    "per_page": 10,
    "to": 10,
    "total": 50
  },
  "links": {
    "first": "https://your-domain.com/api/v1/posts?page=1",
    "last": "https://your-domain.com/api/v1/posts?page=5",
    "prev": null,
    "next": "https://your-domain.com/api/v1/posts?page=2"
  }
}

Error

json
{
  "error": true,
  "data": null,
  "message": "Error description"
}

Validation Error (422)

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

Push Notifications (FCM)

Botble CMS integrates with Firebase Cloud Messaging (FCM v1 API) to send push notifications to mobile app users.

Firebase Setup

  1. Create a project at Firebase Console.
  2. Go to Project Settings > Service Accounts.
  3. Click Generate new private key to download the service account JSON file.
  4. In Admin > Settings > API, under Push Notifications:
    • Enable Push Notifications
    • Enter your Firebase Project ID
    • Upload the service account JSON file

The file is stored in storage/app/firebase/ and validated for required fields (project_id, private_key, client_email).

Device Token Registration

Your mobile app must register its FCM token with the API after obtaining it from Firebase SDK:

bash
POST /api/v1/device-tokens
Content-Type: application/json

{
  "token": "fcm-device-token-from-firebase-sdk",
  "platform": "android",
  "device_id": "unique-device-identifier",
  "app_version": "1.0.0"
}
  • token (required) — The FCM registration token
  • platformandroid or ios
  • device_id — Unique device identifier (for deduplication)
  • app_version — Your app version

If the token already exists, it updates the existing record instead of creating a duplicate.

"No active device tokens found"

This message in the admin panel means no mobile app has registered a device token yet. This is normal if:

  • The mobile app hasn't been built or released yet
  • No users have opened the app since FCM integration was added
  • The app isn't calling the /api/v1/device-tokens endpoint

Device tokens appear automatically once users open the mobile app and the app registers its FCM token.

Sending Notifications from Admin

Use the Send Custom Notification form at Admin > Settings > API:

FieldRequiredDescription
TitleYesNotification title (max 100 characters)
MessageYesNotification body (max 500 characters)
Target DevicesAll Devices, Android only, iOS only, or Customers only
Action URLNoURL to open when notification is tapped
Image URLNoImage to display in the notification

Sending Notifications via Command Line

bash
php artisan api:send-notification --title="Sale!" --message="50% off all items today"

Notification Tracking

Each notification tracks:

  • Sent count — How many devices received the message
  • Failed count — How many deliveries failed
  • Delivered count — Confirmed deliveries
  • Read count — How many users read the notification

Users can retrieve their notifications via the /api/v1/notifications endpoints and mark them as read or clicked.

Scheduled Notifications

Notifications can be scheduled for future delivery. A command processes due notifications:

bash
php artisan schedule:run

Ensure your cronjob is configured for scheduled notifications to work.

Custom API Endpoints

You can add custom endpoints in your plugin:

1. Create an API Controller

php
<?php

namespace Botble\YourPlugin\Http\Controllers\API;

use Botble\Api\Http\Controllers\ApiController;
use Botble\YourPlugin\Models\YourModel;
use Botble\YourPlugin\Http\Resources\YourModelResource;
use Illuminate\Http\Request;

class YourModelController extends ApiController
{
    public function index(Request $request)
    {
        $data = YourModel::query()
            ->paginate($request->input('per_page', 10));

        return $this->respondWithData(YourModelResource::collection($data));
    }

    public function show(int|string $id)
    {
        $item = YourModel::query()->findOrFail($id);

        return $this->respondWithData(new YourModelResource($item));
    }
}

2. Create a Resource

php
<?php

namespace Botble\YourPlugin\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class YourModelResource extends JsonResource
{
    public function toArray($request): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'description' => $this->description,
            'created_at' => $this->created_at->format('Y-m-d H:i:s'),
            'updated_at' => $this->updated_at->format('Y-m-d H:i:s'),
        ];
    }
}

3. Register Routes

php
<?php

namespace Botble\YourPlugin\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Route;

class YourPluginServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Route::group([
            'prefix' => 'api/v1',
            'namespace' => 'Botble\YourPlugin\Http\Controllers\API',
            'middleware' => ['api', 'auth:sanctum'],
        ], function () {
            Route::apiResource('your-models', 'YourModelController');
        });
    }
}

API Documentation Generation

Generate browsable API documentation using Scribe:

bash
composer require knuckleswtf/scribe
php artisan scribe:generate

Access documentation at https://your-domain.com/docs.

API Versioning

All endpoints use the /api/v1/ prefix. To create a new API version, add a separate set of controllers and routes with a /api/v2/ prefix.