PHPackages                             castle/castle-php - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. castle/castle-php

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

castle/castle-php
=================

PHP bindings for Castle

4.0.0(3w ago)8270.2k↑50.4%71MITPHPPHP &gt;=7.2CI passing

Since Jun 27Pushed 3w ago17 watchersCompare

[ Source](https://github.com/castle/castle-php)[ Packagist](https://packagist.org/packages/castle/castle-php)[ Docs](https://github.com/castle/castle-php)[ RSS](/packages/castle-castle-php/feed)WikiDiscussions develop Synced yesterday

READMEChangelog (10)Dependencies (3)Versions (30)Used By (1)

PHP SDK for Castle
==================

[](#php-sdk-for-castle)

[![Specs](https://github.com/castle/castle-php/actions/workflows/specs.yml/badge.svg)](https://github.com/castle/castle-php/actions/workflows/specs.yml)[![Lint](https://github.com/castle/castle-php/actions/workflows/lint.yml/badge.svg)](https://github.com/castle/castle-php/actions/workflows/lint.yml)[![Latest Stable Version](https://camo.githubusercontent.com/f5879675ee3e5028a420821f485a9cae7a956facad83cdebdc78f99d4de4d731/68747470733a2f2f706f7365722e707567782e6f72672f636173746c652f636173746c652d7068702f762f737461626c652e737667)](https://packagist.org/packages/castle/castle-php)

**[Castle](https://castle.io) analyzes user behavior in web and mobile apps to stop fraud before it happens.**

Usage
-----

[](#usage)

See the [documentation](https://docs.castle.io) for how to use this SDK with the Castle APIs

Requirements
------------

[](#requirements)

PHP 7.2 or newer, with the `curl` and `json` extensions. The library is tested against PHP 7.2 through 8.5.

Getting started
---------------

[](#getting-started)

Install the latest version with Composer:

```
composer require castle/castle-php
```

Then load Composer's autoloader and configure the library with your Castle API secret:

```
require_once 'vendor/autoload.php';

Castle::setApiKey('YOUR_API_SECRET');
```

Namespaces
----------

[](#namespaces)

As of 4.0 the library lives under the `Castle\` namespace, e.g. `Castle\Castle`, `Castle\Webhook`, `Castle\RequestContext`, `Castle\ApiError`. This is the canonical API:

```
use Castle\Castle;
use Castle\Webhook;
use Castle\WebhookVerificationError;

Castle::setApiKey('YOUR_API_SECRET');

$verdict = Castle::filter([
  'request_token' => $requestToken,
  'name' => '$registration',
  'user' => ['id' => '1234'],
]);

try {
  Webhook::verify();
} catch (WebhookVerificationError $e) {
  // reject the request
}
```

### Backward compatibility

[](#backward-compatibility)

The historic global class names (`Castle`, `Castle_*`, `RestModel`) are kept as aliases of their namespaced counterparts, so existing integrations keep working without changes. `Castle_ApiError` and `Castle\ApiError` are the same class, so `instanceof` checks and `catch` blocks work with either name:

```
try {
  Castle::risk([/* ... */]);
} catch (Castle_ApiError $e) {
  // still catches the namespaced Castle\ApiError thrown by the library
}
```

New code should prefer the namespaced names; the global aliases are retained for compatibility.

Optional Configurations
-----------------------

[](#optional-configurations)

Set the per-request timeout in milliseconds (applied to both connection and transfer). Defaults to `1000`:

```
Castle::setRequestTimeout(1500);
```

Set the failover strategy used when a `risk` or `filter` request cannot be completed (see [Failover](#failover)):

```
Castle::setFailoverStrategy(Castle\Failover::ALLOW);
```

Set a specified list of request headers to include with event context (optional, not recommended):

```
Castle::setUseAllowlist($headers)
```

Request context
---------------

[](#request-context)

By default, Castle extracts all the necessary information, such as IP and request headers, from the PHP globals in order to build and send the requests to the Castle API. However in some cases you want to track data to Castle from a context where these globals are not available, eg. when tracking async in a background worker. In this case you can build the request context manually.

### Origin IP Address

[](#origin-ip-address)

By default, the SDK extracts the contextual client IP address from headers in the following priority:

1. `X-Forwarded-For`
2. `X-Real-Ip`
3. `REMOTE_ADDR`

If the true client IP address is not specified in the above headers, you can manually set the IP address like so:

```
Castle_RequestContext['ip'] = '1.1.1.1'
$context = Castle_RequestContext::extractJson();
```

Lists
-----

[](#lists)

Manage [lists](https://docs.castle.io) and their items:

```
$list = Castle::createList([
  'name' => 'Blocklist',
  'color' => '$red',
  'primary_field' => 'user.email',
]);

$lists = Castle::getAllLists();
$list  = Castle::getList($list['id']);
Castle::updateList($list['id'], ['name' => 'Renamed']);
Castle::deleteList($list['id']);
Castle::queryList(['filters' => [['field' => 'name', 'op' => '$eq', 'value' => 'Blocklist']]]);
```

List items:

```
$item = Castle::createListItem($list['id'], [
  'author' => 'user:123',
  'primary_value' => 'user@example.com',
]);

Castle::getListItem($list['id'], $item['id']);
Castle::updateListItem($list['id'], $item['id'], ['comment' => 'Flagged for review']);
Castle::queryListItems($list['id'], ['filters' => []]);
Castle::countListItems($list['id'], ['filters' => []]);
Castle::archiveListItem($list['id'], $item['id']);
Castle::unarchiveListItem($list['id'], $item['id']);
Castle::createListItems($list['id'], ['items' => [/* ... */]]);
```

Privacy
-------

[](#privacy)

Request or delete the data Castle stores for a user:

```
Castle::requestUserData([
  'identifier' => 'user@example.com',
  'identifier_type' => '$email',
]);

Castle::deleteUserData([
  'identifier' => 'user@example.com',
  'identifier_type' => '$email',
]);
```

Failover
--------

[](#failover)

When a `risk` or `filter` request cannot be completed because of a network error, timeout or a `5xx` response from the Castle API, the SDK returns a synthetic decision instead of throwing, so your authentication flow keeps working. The decision is controlled by the failover strategy:

```
Castle::setFailoverStrategy(Castle\Failover::ALLOW); // default
// Castle\Failover::DENY
// Castle\Failover::CHALLENGE
// Castle\Failover::THROW  -- re-raise the underlying exception instead
```

A failed-over response carries `failover => true` and a `failover_reason`:

```
$verdict = Castle::risk([
  'request_token' => $requestToken,
  'name' => '$login',
  'user' => ['id' => '1234'],
]);

$verdict->failover;        // true when the request failed over
$verdict->action;          // 'allow', 'deny' or 'challenge'
$verdict->policy['action'];
```

Successful responses include `failover => false`. Client errors (`4xx`, such as `422 invalid_request_token`) are never failed over and always raise.

Do-not-track
------------

[](#do-not-track)

Disable outbound tracking calls, for example in staging or test environments. While disabled, `risk`, `filter` and `log` return an `allow` response without contacting the API:

```
Castle::disableTracking();
Castle::tracked();        // false
Castle::enableTracking();
```

Events (enterprise)
-------------------

[](#events-enterprise)

Query event data:

```
Castle::eventsSchema();
Castle::queryEvents(['filters' => [['field' => 'name', 'op' => '$eq', 'value' => '$login']]]);
Castle::groupEvents(['filters' => [], 'group_by' => 'name']);
```

Webhooks
--------

[](#webhooks)

Verify the authenticity of incoming Castle webhooks. By default the raw body is read from `php://input` and the signature from the `X-Castle-Signature` header:

```
try {
  Castle_Webhook::verify();
  // handle the webhook payload
} catch (Castle_WebhookVerificationError $e) {
  http_response_code(404);
}
```

The body and signature can also be passed explicitly:

```
Castle_Webhook::verify($rawBody, $signatureHeader);
```

Errors
------

[](#errors)

Whenever something unexpected happens, an [exception](lib/Castle/Errors.php) is thrown to indicate what went wrong.

NameDescription`Castle_Error`A generic error`Castle_RequestError`A request failed. Probably due to a network error`Castle_ApiError`An unexpected error for the Castle API`Castle_InternalServerError`The Castle API returned a `5xx` response (triggers failover)`Castle_ConfigurationError`The Castle secret API key has not been set`Castle_UnauthorizedError`Wrong Castle API secret key`Castle_BadRequest`The request was invalid. For example if a challenge is created without the user having MFA enabled.`Castle_ForbiddenError`The user has entered the wrong code too many times and a new challenge has to be requested.`Castle_NotFoundError`The resource requestd was not found. For example if a session has been revoked.`Castle_InvalidParametersError`One or more of the supplied parameters are incorrect. Check the response for more information.`Castle_InvalidRequestTokenError`The request token parameter is missing or invalid`Castle_WebhookVerificationError`An incoming webhook could not be verified against the `X-Castle-Signature` headerRunning test suite
------------------

[](#running-test-suite)

Install the dev dependencies and run the suite with:

```
composer install
composer test
```

###  Health Score

61

—

FairBetter than 98% of packages

Maintenance95

Actively maintained with recent releases

Popularity43

Moderate usage in the ecosystem

Community24

Small or concentrated contributor base

Maturity69

Established project with proven stability

 Bus Factor1

Top contributor holds 71.8% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~207 days

Recently: every ~506 days

Total

22

Last Release

23d ago

Major Versions

1.7.0 → 2.0.02019-07-26

2.1.0 → 3.0.02021-06-03

3.2.0 → 4.0.02026-06-10

PHP version history (4 changes)1.0.0PHP &gt;=5.3.2

1.4.0PHP &gt;=5.6.0

2.0.0PHP &gt;=7.2.0

4.0.0PHP &gt;=7.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/4f78a6b633ad45fd5c5139daee3b453d339321844254c0cbec502d43735a89ff?d=identicon)[castle](/maintainers/castle)

---

Top Contributors

[![wallin](https://avatars.githubusercontent.com/u/268917?v=4)](https://github.com/wallin "wallin (191 commits)")[![lluft](https://avatars.githubusercontent.com/u/617198?v=4)](https://github.com/lluft "lluft (31 commits)")[![brissmyr](https://avatars.githubusercontent.com/u/238031?v=4)](https://github.com/brissmyr "brissmyr (21 commits)")[![bartes](https://avatars.githubusercontent.com/u/93064?v=4)](https://github.com/bartes "bartes (14 commits)")[![joladev](https://avatars.githubusercontent.com/u/297627?v=4)](https://github.com/joladev "joladev (3 commits)")[![afterdesign](https://avatars.githubusercontent.com/u/672767?v=4)](https://github.com/afterdesign "afterdesign (3 commits)")[![marysieek](https://avatars.githubusercontent.com/u/7430071?v=4)](https://github.com/marysieek "marysieek (1 commits)")[![szphie](https://avatars.githubusercontent.com/u/3667695?v=4)](https://github.com/szphie "szphie (1 commits)")[![brunov25](https://avatars.githubusercontent.com/u/1091322?v=4)](https://github.com/brunov25 "brunov25 (1 commits)")

---

Tags

castlefraud-detectionfraud-preventionphpsdkreal-time user account monitoring

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/castle-castle-php/health.svg)

```
[![Health](https://phpackages.com/badges/castle-castle-php/health.svg)](https://phpackages.com/packages/castle-castle-php)
```

###  Alternatives

[lukapeharda/tailwindcss-color-palette-generator

Generate TailwindCSS color palette from a single color.

22113.3k1](/packages/lukapeharda-tailwindcss-color-palette-generator)[flagstudio/laravel-paginate

Different paginate macros for laravel eloquent builder and collection

158.5k](/packages/flagstudio-laravel-paginate)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
