Skip to main content
The client credentials grant lets an external application authenticate directly as an app client — without any user involvement. The app client uses its own roles and permissions to determine what it can access.

When to Use

Use client credentials when:
  • A third-party system or integration needs to read or write data (e.g. syncing schools from an external platform).
  • You are building an embedded experience on an external website that calls your API on behalf of your organization.
  • You need an “admin API” that external automation tools can call.
  • The request does not involve an individual user’s context.

How It Works

1

App client authenticates

The external application sends its client_id and client_secret to the token endpoint and receives an access token.
2

Token is used for API requests

The token is attached to subsequent requests in the Authorization header. The app client’s Spatie roles and permissions determine what the request can access.
3

Token expires

Tokens have a limited lifetime. The application requests a new token when needed.

Setting Up

1. Create an App Client

In Developer → Apps, create a new app client with Client credentials as the grant type. See App Clients for the full setup steps.

2. Assign Permissions

On the client’s Permissions tab, assign the roles and/or individual permissions that the integration should have. Only grant the minimum permissions required.

3. Obtain an Access Token

The external application exchanges its credentials for an access token:
curl -X POST https://yourapp.test/oauth/token \
  -H 'Content-Type: application/json' \
  -d '{
    "grant_type": "client_credentials",
    "client_id": "your-client-uuid",
    "client_secret": "your-client-secret",
    "scope": ""
  }'
{
  "token_type": "Bearer",
  "expires_in": 31536000,
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..."
}

4. Make Authenticated Requests

Use the token in the Authorization header on any /api/v1/* route:
cURL
curl -X GET https://yourapp.test/api/v1/schools \
  -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...'

Defining API Routes

API routes are defined in routes/api.php under the /v1 prefix using the CoreApiAuthenticate middleware, which accepts both client credentials tokens and user access tokens:
routes/api.php
use Inly\Core\Http\Middleware\CoreApiAuthenticate;

Route::middleware([CoreApiAuthenticate::class])
    ->prefix('v1')
    ->group(function () {
        Route::get('/schools', [Api\SchoolController::class, 'index']);
    });
Inside controllers, use Auth::guard('api')->client() to retrieve the authenticated app client (returns null for user tokens), or $request->user() for user tokens.

Permission Checks

Inside a controller, you can check the app client’s permissions using the same Gate and can() methods as for users:
Route::middleware([CoreApiAuthenticate::class])
    ->prefix('v1')
    ->group(function () {
        Route::get('/schools', function () {
            abort_unless(
                auth()->user()?->can('view_schools') ?? Auth::guard('api')->client()?->can('view_schools'),
                403,
                'Missing permission to view schools.'
            );

            return School::all();
        });
    });

Next Steps