nickmoline / stytch-php
Stytch PHP SDK
Requires
- php: ^8.2
- ext-curl: *
- ext-json: *
- guzzlehttp/guzzle: ^7.0
- guzzlehttp/psr7: ^2.7
- nesbot/carbon: ^3.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.76
- larapack/dd: ^1.1
- pestphp/pest: ^3.8
- phpstan/phpstan: ^2.1
- phpstan/phpstan-phpunit: ^2.0
- phpunit/php-code-coverage: ^11.0
- phpunit/phpunit: ^11.0
- vlucas/phpdotenv: ^5.6
This package is auto-updated.
Last update: 2025-07-04 05:48:03 UTC
README
Unofficial PHP SDK for Stytch based on the Official Stytch Node.js Library.
Installation
composer require nickmoline/stytch-php
Requirements
- PHP 8.2 or higher
- Guzzle HTTP Client
- PSR-7 compatible HTTP messages
Usage
You can find your API credentials in the Stytch Dashboard.
Basic Setup
<?php use Stytch\Stytch; $stytch = new Stytch([ 'project_id' => 'project-live-c60c0abe-c25a-4472-a9ed-320c6667d317', 'secret' => 'secret-live-80JASucyk7z_G8Z-7dVwZVGXL5NT_qGAQ2I=', ]);
B2B Features
This library currently supports the following B2B features:
- Organizations
- Magic Links
- Sessions
- Discovery
- Impersonation
- OAuth
- OTPs (SMS & Email)
- Passwords
- RBAC
- Recovery Codes
- SCIM
- SSO
- TOTPs
- IDP
B2C Features
This library currently supports the following B2C features:
- Users
- Magic Links (Email)
- Sessions
- OAuth
- OTPs (SMS, Email, WhatsApp)
- Passwords
- TOTPs
- WebAuthn
- Crypto Wallets
- Fraud Detection
- Project Management
- Impersonation
- IDP
- M2M
- Attributes
Object-Based Responses
The library returns proper PHP objects instead of raw arrays, providing better type safety and IDE support. All responses include a request_id
and status_code
for debugging purposes.
Note: B2B responses return structured objects, while B2C responses return arrays. This difference reflects the underlying API structure.
Carbon Date Handling
All date and time fields from the Stytch API are automatically converted to Carbon instances, providing rich date manipulation capabilities:
$response = $stytch->b2b()->organizations->get('org_id'); $organization = $response->organization; // Access Carbon instances for date fields $createdAt = $organization->created_at; // Carbon instance $updatedAt = $organization->updated_at; // Carbon instance // Use Carbon's rich date manipulation echo $createdAt->format('Y-m-d H:i:s'); // "2023-01-01 12:00:00" echo $createdAt->diffForHumans(); // "2 days ago" echo $createdAt->isToday(); // true/false echo $createdAt->addDays(7)->format('Y-m-d'); // Add 7 days // Session expiration handling $session = $response->member_session; $expiresAt = $session->expires_at; // Carbon instance if ($expiresAt->isPast()) { echo "Session has expired"; } else { echo "Session expires in " . $expiresAt->diffForHumans(); }
Available Carbon date fields:
created_at
- When the resource was createdupdated_at
- When the resource was last updatedexpires_at
- When a session or token expiresstarted_at
- When a session startedlast_accessed_at
- When a session was last accessedlock_created_at
- When a user/member lock was createdlock_expires_at
- When a user/member lock expireslast_authenticated_at
- When authentication factor was last usedbearer_token_expires_at
- When a bearer token expires
Implementation Details:
The library uses a HasCarbonDates
trait to handle date parsing consistently across all object classes. This trait provides:
parseDate(?string $date): ?Carbon
- Safely parse date strings to Carbon instancesparseDates(array $dates): array
- Parse multiple date strings at oncetoDateString(?Carbon $date): ?string
- Convert Carbon instances back to ISO stringstoDateStrings(array $dates): array
- Convert multiple Carbon instances at once
This approach ensures consistent date handling and reduces code duplication throughout the library.
B2B Response Format (Object-based)
$response = $stytch->b2b()->organizations->get('org_id'); $organization = $response->organization; // Object echo $organization->organization_name; // Property access echo $response->request_id; // Debug info
B2C Response Format (Array-based)
$response = $stytch->b2c()->users->get('user_id'); echo $response['user_id']; // Array access echo $response['emails'][0]['email']; // Nested array access
B2B Examples
Create an Organization
$response = $stytch->b2b()->organizations->create([ 'organization_name' => 'Acme Co', 'organization_slug' => 'acme-co', 'email_allowed_domains' => ['acme.co'], ]); // Access the organization object $organization = $response->organization; echo $organization->organization_name; // "Acme Co" echo $organization->organization_id; // "org_1234567890abcdef" echo $response->request_id; // For debugging
Get an Organization
$response = $stytch->b2b()->organizations->get('org_1234567890abcdef'); $organization = $response->organization; echo $organization->organization_name; echo $organization->organization_slug; echo $organization->email_allowed_domains[0]; // Access array properties
Update an Organization
$response = $stytch->b2b()->organizations->update('org_1234567890abcdef', [ 'organization_name' => 'Acme Corporation', 'email_allowed_domains' => ['acme.co', 'acmecorp.com'], ]); $organization = $response->organization; echo $organization->organization_name; // "Acme Corporation"
Delete an Organization
$result = $stytch->b2b()->organizations->delete('org_1234567890abcdef');
Search Organizations
$response = $stytch->b2b()->organizations->search([ 'limit' => 10, 'query' => [ 'operator' => 'AND', 'operands' => [ [ 'filter_name' => 'organization_name_fuzzy', 'filter_value' => 'Acme' ] ] ] ]); // Access the organizations array $organizations = $response->organizations; foreach ($organizations as $org) { echo $org->organization_name; echo $org->organization_id; } // Access metadata echo $response->results_metadata['total'];
Send Magic Link for Login/Signup
$result = $stytch->b2b()->magicLinks->loginOrSignup([ 'organization_id' => 'org_1234567890abcdef', 'email_address' => 'admin@acme.co', ]);
Authenticate Magic Link
$response = $stytch->b2b()->magicLinks->authenticate([ 'token' => 'DOYoip3rvIMMW5lgItikFK-Ak1CfMsgjuiCyI7uuU94=', ]); // Access session and member information echo $response->session_token; echo $response->session_jwt; echo $response->member->email_address; echo $response->organization->organization_name; echo $response->member_authenticated; // boolean
Authenticate Session
$response = $stytch->b2b()->sessions->authenticate([ 'session_token' => 'session_token_here', ]); echo $response->session_token; echo $response->session_jwt; echo $response->member->member_id; echo $response->organization->organization_id; // Access session details $session = $response->member_session; echo $session->member_session_id; echo $session->expires_at; echo $session->roles[0]; // Access roles array
Get Session
$session = $stytch->b2b()->sessions->get('session_1234567890abcdef');
Revoke Session
$result = $stytch->b2b()->sessions->revoke('session_1234567890abcdef');
Password Authentication
$response = $stytch->b2b()->passwords->authenticate([ 'organization_id' => 'org_1234567890abcdef', 'email_address' => 'admin@acme.co', 'password' => 'user_password', ]); echo $response->member_id; echo $response->organization_id; echo $response->session_token; echo $response->member_authenticated; echo $response->member->email_address;
Password Strength Check
$response = $stytch->b2b()->passwords->strengthCheck([ 'password' => 'user_password', 'email_address' => 'admin@acme.co', ]); echo $response->valid_password; // boolean echo $response->score; // integer echo $response->breached_password; // boolean echo $response->strength_policy;
OAuth Authentication
$result = $stytch->b2b()->oauth->authenticate([ 'oauth_token' => 'oauth_token_here', ]);
Send SMS OTP
$result = $stytch->b2b()->otps->sms->send([ 'organization_id' => 'org_1234567890abcdef', 'member_id' => 'member_1234567890abcdef', ]);
Authenticate SMS OTP
$result = $stytch->b2b()->otps->sms->authenticate([ 'organization_id' => 'org_1234567890abcdef', 'member_id' => 'member_1234567890abcdef', 'code' => '123456', ]);
Send Email OTP
$result = $stytch->b2b()->otps->email->send([ 'organization_id' => 'org_1234567890abcdef', 'member_id' => 'member_1234567890abcdef', ]);
Authenticate Email OTP
$result = $stytch->b2b()->otps->email->authenticate([ 'organization_id' => 'org_1234567890abcdef', 'member_id' => 'member_1234567890abcdef', 'code' => '123456', ]);
Create TOTP
$result = $stytch->b2b()->totps->create([ 'organization_id' => 'org_1234567890abcdef', 'member_id' => 'member_1234567890abcdef', ]);
Authenticate TOTP
$result = $stytch->b2b()->totps->authenticate([ 'organization_id' => 'org_1234567890abcdef', 'member_id' => 'member_1234567890abcdef', 'code' => '123456', ]);
Get Recovery Codes
$result = $stytch->b2b()->recoveryCodes->get([ 'organization_id' => 'org_1234567890abcdef', 'member_id' => 'member_1234567890abcdef', ]);
Recover with Recovery Code
$result = $stytch->b2b()->recoveryCodes->recover([ 'organization_id' => 'org_1234567890abcdef', 'member_id' => 'member_1234567890abcdef', 'recovery_code' => 'recovery_code_here', ]);
Discovery - List Organizations
$result = $stytch->b2b()->discovery->organizations->list([ 'intermediate_session_token' => 'token_here', ]);
Discovery - Create Organization
$result = $stytch->b2b()->discovery->organizations->create([ 'intermediate_session_token' => 'token_here', 'organization_name' => 'New Organization', ]);
Discovery - Get Organization
$result = $stytch->b2b()->discovery->organizations->get([ 'intermediate_session_token' => 'token_here', 'organization_id' => 'org_1234567890abcdef', ]);
Discovery - Update Organization
$result = $stytch->b2b()->discovery->organizations->update([ 'intermediate_session_token' => 'token_here', 'organization_id' => 'org_1234567890abcdef', 'organization_name' => 'Updated Organization Name', ]);
Discovery - Delete Organization
$result = $stytch->b2b()->discovery->organizations->delete([ 'intermediate_session_token' => 'token_here', 'organization_id' => 'org_1234567890abcdef', ]);
SSO Authentication
$result = $stytch->b2b()->sso->authenticate([ 'sso_token' => 'sso_token_here', ]);
Get SSO Connections
$result = $stytch->b2b()->sso->getConnections([ 'organization_id' => 'org_1234567890abcdef', ]);
Delete SSO Connection
$result = $stytch->b2b()->sso->deleteConnection([ 'organization_id' => 'org_1234567890abcdef', 'connection_id' => 'connection_1234567890abcdef', ]);
SCIM Connection Management
// Create SCIM connection $result = $stytch->b2b()->scim->connection->create([ 'organization_id' => 'org_1234567890abcdef', 'display_name' => 'SCIM Connection', 'base_url' => 'https://example.com/scim', 'bearer_token' => 'token_here', ]); // Get SCIM connection $result = $stytch->b2b()->scim->connection->get([ 'organization_id' => 'org_1234567890abcdef', 'connection_id' => 'connection_1234567890abcdef', ]);
IDP Token Introspection
$result = $stytch->b2b()->idp->introspectToken([ 'token' => 'token_here', 'client_id' => 'client_id_here', ]);
IDP - Get Token
$result = $stytch->b2b()->idp->getToken([ 'token' => 'token_here', ]);
Impersonation - Authenticate
$result = $stytch->b2b()->impersonation->authenticate([ 'impersonation_token' => 'impersonation_token_here', ]);
RBAC Policy
$result = $stytch->b2b()->rbac->policy();