PHPackages                             sk-id-solutions/smart-id-php-client - 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. [API Development](/categories/api)
4. /
5. sk-id-solutions/smart-id-php-client

ActiveLibrary[API Development](/categories/api)

sk-id-solutions/smart-id-php-client
===================================

Smart-ID Relying Party PHP Api client

v2.3.3(1y ago)22971.0k↓11.9%15[2 issues](https://github.com/SK-EID/smart-id-php-client/issues)1MITPHPPHP &gt;=7.4CI passing

Since Apr 20Pushed 1mo ago9 watchersCompare

[ Source](https://github.com/SK-EID/smart-id-php-client)[ Packagist](https://packagist.org/packages/sk-id-solutions/smart-id-php-client)[ Docs](https://github.com/SK-EID/smart-id-php-client)[ RSS](/packages/sk-id-solutions-smart-id-php-client/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (2)Versions (22)Used By (1)

Smart-ID PHP client
===================

[](#smart-id-php-client)

This library supports Smart-ID API v3.

Table of contents
-----------------

[](#table-of-contents)

- [Introduction](#introduction)
- [Features](#features)
- [Requirements](#requirements)
- [Getting the library](#getting-the-library)
- [Changelog](#changelog)
- [How to use it with RP API v3](#how-to-use-it-with-rp-api-v3)
    - [Test accounts for testing](#test-accounts-for-testing)
        - [Uploading certificates to demo OCSP](#uploading-certificates-to-demo-ocsp)
    - [Setting up SmartIdClient](#setting-up-smartidclient)
    - [Setting up the connector](#setting-up-the-connector)
        - [Setting up HTTPS public key pinning](#setting-up-https-public-key-pinning)
    - [Device link flows](#device-link-flows)
        - [Device link authentication session](#device-link-authentication-session)
            - [Using the request builder](#using-the-request-builder)
            - [Using request objects directly](#using-request-objects-directly)
        - [Generating QR code or device link](#generating-qr-code-or-device-link)
        - [Examples of allowed device link interactions](#examples-of-allowed-device-link-interactions)
    - [Notification-based flows](#notification-based-flows)
        - [Differences between notification-based and device link flows](#differences-between-notification-based-and-device-link-flows)
        - [Notification-based authentication session](#notification-based-authentication-session)
            - [With semantics identifier](#initiating-with-semantics-identifier)
            - [With document number](#initiating-with-document-number)
        - [Examples of allowed notification-based interactions](#examples-of-allowed-notification-based-interactions)
    - [Querying session status](#querying-session-status)
        - [Session status response](#session-status-response)
            - [End result values](#end-result-values)
            - [End result to exception mapping](#end-result-to-exception-mapping)
        - [Polling for final session status](#polling-for-final-session-status)
        - [Single status query](#single-status-query)
    - [Validating authentication response](#validating-authentication-response)
        - [Setting up trusted CA certificates](#setting-up-trusted-ca-certificates)
        - [OCSP certificate revocation checking](#ocsp-certificate-revocation-checking)
        - [Validating device link authentication](#validating-device-link-authentication)
        - [Validating notification-based authentication](#validating-notification-based-authentication)
        - [Web2App flow validation](#web2app-flow-validation)
        - [Validating callback URL with CallbackUrlUtil](#validating-callback-url-with-callbackurlutil)
    - [Extracting user identity](#extracting-user-identity)
    - [Additional request properties](#additional-request-properties)
        - [Requesting IP address of user's device](#requesting-ip-address-of-users-device)
    - [Exception handling](#exception-handling)
- [Logging](#logging)

Introduction
------------

[](#introduction)

The Smart-ID PHP client can be used for easy integration of the [Smart-ID](https://www.smart-id.com) solution to information systems or e-services.

Features
--------

[](#features)

- User authentication (device link and notification-based flows)
- SmartIdClient facade for simplified integration
- Built-in HTTPS public key pinning for secure API communication
- QR code and Web2App device link URL generation
- ACSP\_V2 signature protocol with RSA-PSS verification
- SHA-256, SHA-384, SHA-512, SHA3-256, SHA3-384, SHA3-512 hash algorithm support
- Certificate trust chain validation with full signatureAlgorithmParameters validation
- OCSP certificate revocation checking via AIA or designated responder
- Verification code calculation
- CallbackUrlUtil for Web2App/App2App callback URL creation and validation
- Optional PSR-3 logging support

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

[](#requirements)

- PHP &gt;= 8.4
- ext-openssl (for certificate parsing and signature verification)
- ext-json (for API request/response serialization)
- ext-curl (for HTTPS pinning via `CURLOPT_PINNEDPUBLICKEY`)

Getting the library
-------------------

[](#getting-the-library)

Install via [Composer](https://getcomposer.org/):

```
composer require sk-id-solutions/smart-id-php-client
```

Changelog
---------

[](#changelog)

Changes introduced with new library versions are described in [CHANGELOG.md](CHANGELOG.md).

How to use it with RP API v3
============================

[](#how-to-use-it-with-rp-api-v3)

Import the relevant classes from the `Sk\SmartId` namespace:

```
use Sk\SmartId\Api\SmartIdRestConnector;
use Sk\SmartId\Ssl\SslPinnedPublicKeyStore;
```

Test accounts for testing
-------------------------

[](#test-accounts-for-testing)

[Test accounts for testing](https://sk-eid.github.io/smart-id-documentation/test_accounts.html)

> **Note:** Smart-ID Basic level accounts (certificate level `ADVANCED`) are not supported in the demo environment.

### Uploading certificates to demo OCSP

[](#uploading-certificates-to-demo-ocsp)

Smart-ID demo certificates are **not** automatically available in the demo AIA OCSP responder (`aia.demo.sk.ee`). To make them available for OCSP revocation checking, upload them via SK's certificate upload interface:

- **Upload page:** [https://demo.sk.ee/upload\_cert/](https://demo.sk.ee/upload_cert/) — upload certificates and set their OCSP status (good/revoked/unknown)
- **Download demo certificates:**  — log in to the Smart-ID self-service portal to download certificates
- **Demo OCSP info:**

Setting up SmartIdClient
------------------------

[](#setting-up-smartidclient)

`SmartIdClient` is the main entry point for using Smart-ID services. It wires together the connector, session status poller, and request builders.

```
use Sk\SmartId\SmartIdClient;
use Sk\SmartId\Ssl\SslPinnedPublicKeyStore;

// Demo environment
$client = new SmartIdClient(
    relyingPartyUUID: '00000000-0000-4000-8000-000000000000',
    relyingPartyName: 'DEMO',
    hostUrl: 'https://sid.demo.sk.ee/smart-id-rp/v3',
    sslPinnedKeys: SslPinnedPublicKeyStore::loadDemo(),
);

// Production environment with logging (see "Logging" section below)
$sslKeys = SslPinnedPublicKeyStore::create()
    ->addPublicKeyHash('sha256//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX=')
    ->addPublicKeyHash('sha256//YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY=');

$client = new SmartIdClient(
    relyingPartyUUID: 'your-relying-party-uuid',
    relyingPartyName: 'Your RP Name',
    hostUrl: 'https://rp-api.smart-id.com/v3',
    sslPinnedKeys: $sslKeys,
    logger: $logger, // optional PSR-3 LoggerInterface
);

// Create authentication builders directly from the client
$deviceLinkBuilder = $client->createDeviceLinkAuthentication();
$notificationBuilder = $client->createNotificationAuthentication();

// Get the session status poller
$poller = $client->getSessionStatusPoller();

// Create validator (OCSP revocation checking is enabled automatically)
$validator = $client->createAuthenticationResponseValidator();

// Configure polling parameters (optional)
$client->setPollTimeoutMs(30000);
$client->setPollIntervalMs(1000);
```

You can also use the connector directly for lower-level control (see [Setting up the connector](#setting-up-the-connector)).

Setting up the connector
------------------------

[](#setting-up-the-connector)

[Configure to use with Smart-ID Demo environment](https://sk-eid.github.io/smart-id-documentation/environments.html#_demo)

```
use Sk\SmartId\Api\SmartIdRestConnector;
use Sk\SmartId\Ssl\SslPinnedPublicKeyStore;

// Demo environment
$connector = new SmartIdRestConnector(
    'https://sid.demo.sk.ee/smart-id-rp/v3',
    SslPinnedPublicKeyStore::loadDemo(),
);

// Production environment
$sslKeys = SslPinnedPublicKeyStore::create()
    ->addPublicKeyHash('sha256//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX=')
    ->addPublicKeyHash('sha256//YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY=');

$connector = new SmartIdRestConnector('https://rp-api.smart-id.com/v3', $sslKeys);
```

### Setting up HTTPS public key pinning

[](#setting-up-https-public-key-pinning)

HTTPS public key pinning is used to prevent man-in-the-middle attacks against the Smart-ID API connection.

Live SSL certificates: [https://sk-eid.github.io/smart-id-documentation/https\_pinning.html#\_rp\_api\_smart\_id\_com\_certificates](https://sk-eid.github.io/smart-id-documentation/https_pinning.html#_rp_api_smart_id_com_certificates)

Demo SSL certificates: [https://sk-eid.github.io/smart-id-documentation/https\_pinning.html#\_sid\_demo\_sk\_ee\_certificates](https://sk-eid.github.io/smart-id-documentation/https_pinning.html#_sid_demo_sk_ee_certificates)

#### Demo / testing

[](#demo--testing)

For development against `sid.demo.sk.ee`, the SDK bundles demo keys:

```
$connector = new SmartIdRestConnector(
    'https://sid.demo.sk.ee/smart-id-rp/v3',
    SslPinnedPublicKeyStore::loadDemo(),
);
```

#### Providing SSL public key hashes manually

[](#providing-ssl-public-key-hashes-manually)

For production, you must configure your own SPKI hashes. Download the current certificates from [SK's HTTPS pinning documentation](https://sk-eid.github.io/smart-id-documentation/https_pinning.html)and extract each certificate's SPKI hash:

```
openssl x509 -inform PEM -in certificate.pem -noout -pubkey \
  | openssl rsa -pubin -outform der 2>/dev/null \
  | openssl dgst -sha256 -binary \
  | openssl enc -base64
```

Then provide the hashes:

```
$sslKeys = SslPinnedPublicKeyStore::create()
    ->addPublicKeyHash('sha256//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX=')
    ->addPublicKeyHash('sha256//YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY=');

$connector = new SmartIdRestConnector('https://rp-api.smart-id.com/v3', $sslKeys);
```

#### Loading hashes from a directory

[](#loading-hashes-from-a-directory)

You can load hashes from a directory of `.key` files (each containing one `sha256//...` hash):

```
$sslKeys = SslPinnedPublicKeyStore::loadFromDirectory('/path/to/your/keys');
$connector = new SmartIdRestConnector('https://rp-api.smart-id.com/v3', $sslKeys);
```

#### Loading hashes from an environment variable

[](#loading-hashes-from-an-environment-variable)

When hashes are stored in a single environment variable (e.g. from `.env` or container config):

```
SMARTID_SSL_PINS="sha256//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX=,sha256//YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY="
```

```
$sslKeys = SslPinnedPublicKeyStore::fromString(getenv('SMARTID_SSL_PINS'));

$connector = new SmartIdRestConnector('https://rp-api.smart-id.com/v3', $sslKeys);
```

A custom separator can be provided as the second argument:

```
// Semicolon-separated
$sslKeys = SslPinnedPublicKeyStore::fromString(getenv('SMARTID_SSL_PINS'), ';');
```

#### Loading hashes from an array (secret managers, config files)

[](#loading-hashes-from-an-array-secret-managers-config-files)

When your secret manager or configuration returns an array of hash strings:

```
$hashes = $secretManager->getSecret('smartid-ssl-pins'); // returns string[]

$sslKeys = SslPinnedPublicKeyStore::fromArray($hashes);

$connector = new SmartIdRestConnector('https://rp-api.smart-id.com/v3', $sslKeys);
```

All methods that accept hashes (`addPublicKeyHash()`, `fromString()`, `fromArray()`) validate every hash immediately and throw `\InvalidArgumentException` if the format is invalid or the input is empty.

Device link flows
-----------------

[](#device-link-flows)

Device link flows are the more secure way to ensure the user who started the authentication is in control of the device. More info: [https://sk-eid.github.io/smart-id-documentation/rp-api/device\_link\_flows.html](https://sk-eid.github.io/smart-id-documentation/rp-api/device_link_flows.html)

### Device link authentication session

[](#device-link-authentication-session)

#### Request parameters

[](#request-parameters)

- **relyingPartyUUID** — Required. UUID of the Relying Party.
- **relyingPartyName** — Required. Friendly name of the Relying Party, limited to 32 bytes in UTF-8 encoding.
- **certificateLevel** — Level of certificate requested. Possible values: `QUALIFIED`, `ADVANCED`. Defaults to `QUALIFIED`.
- **hashAlgorithm** — Hash algorithm for signatures. Supported: `SHA-256`, `SHA-384`, `SHA-512`, `SHA3-256`, `SHA3-384`, `SHA3-512`. Defaults to `SHA-512`.
- **interactions** — Required. Array of `DeviceLinkInteraction` objects defining the allowed interactions in order of preference.
- **initialCallbackUrl** — Optional. HTTPS callback URL for Web2App same-device flows. Set via `withCallbackUrl()` on the builder.
- **nonce** — Optional. Random string, up to 30 characters. Used to override idempotent behaviour (if the same request is made within a 15-second window, the same response is returned unless a nonce is provided).
- **capabilities** — Optional. Array of capability strings. Used only when agreed with Smart-ID provider.
- **requestProperties** — Optional. Set `shareMdClientIpAddress` to `true` to request the IP address of the user's device (see [Requesting IP address](#requesting-ip-address-of-users-device)).

#### Response parameters

[](#response-parameters)

- **sessionID** — String used to query the session status.
- **sessionToken** — Unique token linking this session between RP, RP-API, and the mobile app.
- **sessionSecret** — Base64-encoded secret key. Keep on backend only, never expose to client.
- **deviceLinkBase** — Base URI for forming device link or QR code URLs.

#### Using the request builder

[](#using-the-request-builder)

```
use Sk\SmartId\DeviceLink\DeviceLinkAuthenticationRequestBuilder;
use Sk\SmartId\Enum\CertificateLevel;
use Sk\SmartId\DeviceLink\DeviceLinkInteraction;

$builder = new DeviceLinkAuthenticationRequestBuilder(
    $connector,
    '00000000-0000-4000-8000-000000000000', // relyingPartyUUID
    'DEMO',                                  // relyingPartyName
);

// Initiate anonymous authentication (no user identifier needed)
$session = $builder
    ->withCertificateLevel(CertificateLevel::QUALIFIED)
    ->withAllowedInteractionsOrder([
        DeviceLinkInteraction::displayTextAndPin('Log in to example.com'),
    ])
    ->initiate();

// Session ID for polling
$sessionId = $session->getSessionId();

// Verification code to display (if using notification-style interaction)
$verificationCode = $session->getVerificationCode();

// Build QR code URL (see "Generating QR code or device link" section)
$qrCodeUrl = $session->buildQrCodeUrl();
```

The builder automatically generates the RP challenge and calculates the verification code. If needed, you can provide your own RP challenge:

```
use Sk\SmartId\Util\RpChallengeGenerator;

$rpChallenge = RpChallengeGenerator::generate();

$session = $builder
    ->withRpChallenge($rpChallenge)
    ->withAllowedInteractionsOrder([
        DeviceLinkInteraction::displayTextAndPin('Log in to example.com'),
    ])
    ->initiate();
```

#### Using request objects directly

[](#using-request-objects-directly)

For lower-level control, construct request objects directly:

```
use Sk\SmartId\DeviceLink\DeviceLinkAuthenticationRequest;
use Sk\SmartId\Enum\CertificateLevel;
use Sk\SmartId\Enum\HashAlgorithm;
use Sk\SmartId\DeviceLink\DeviceLinkInteraction;
use Sk\SmartId\Util\RpChallengeGenerator;

// For security, generate a new challenge for each request
$rpChallenge = RpChallengeGenerator::generate();

$interactions = [DeviceLinkInteraction::displayTextAndPin('Log in to example.com')];

$request = new DeviceLinkAuthenticationRequest(
    relyingPartyUUID: '00000000-0000-4000-8000-000000000000',
    relyingPartyName: 'DEMO',
    rpChallenge: $rpChallenge,
    hashAlgorithm: HashAlgorithm::SHA512,
    allowedInteractionsOrder: $interactions,
    certificateLevel: CertificateLevel::QUALIFIED,
);

$response = $connector->initiateDeviceLinkAuthentication($request);

// Store these on the backend for later use
$sessionId = $response->getSessionID();
$sessionToken = $response->getSessionToken();
$sessionSecret = $response->getSessionSecret(); // Keep secret, do not expose to client
$deviceLinkBase = $response->getDeviceLinkBase();
```

### Generating QR code or device link

[](#generating-qr-code-or-device-link)

Documentation: [https://sk-eid.github.io/smart-id-documentation/rp-api/device\_link\_flows.html](https://sk-eid.github.io/smart-id-documentation/rp-api/device_link_flows.html)

To use the Smart-ID **demo environment**, you must specify `SchemeName::DEMO` as the scheme name (use `->withDemoEnvironment()` or `->withSchemeName(SchemeName::DEMO)`). See: [https://sk-eid.github.io/smart-id-documentation/environments.html#\_demo](https://sk-eid.github.io/smart-id-documentation/environments.html#_demo)

#### Device link parameters

[](#device-link-parameters)

- **deviceLinkBase** — Value from session-init response.
- **deviceLinkType** — `QR` or `WEB2APP`.
- **sessionToken** — Token from the session response.
- **elapsedSeconds** — Seconds since the session-init response was received. Required for QR codes.
- **lang** — User language. Default: `eng`.
- **schemeName** — Controls environment. Default: `SchemeName::PRODUCTION`. Use `SchemeName::DEMO` for demo.
- **callbackUrl** — Required for Web2App flows. Must be HTTPS.
- **brokeredRpName** — Optional. Name of the brokered Relying Party, used when acting as a broker. Included in authCode calculation and must match during validation.

#### Generating QR code URL

[](#generating-qr-code-url)

QR code URLs must be **refreshed every second** because the authCode changes based on elapsed time to prevent replay attacks.

```
// Using the session object (simplest approach)
$session = $builder->initiate();

// QR code URL auto-calculates elapsed time from session creation
$qrCodeUrl = $session->buildQrCodeUrl();

// Or provide elapsed seconds explicitly
$qrCodeUrl = $session->buildQrCodeUrl(elapsedSeconds: 5);
```

Using the `DeviceLinkBuilder` for more control:

```
$qrCodeUrl = $session->createDeviceLinkBuilder()
    ->withElapsedSeconds($elapsedSeconds)
    ->withDemoEnvironment() // for demo environment
    ->withLang('est')       // override language
    ->buildQrCodeUrl();
```

#### Generating Web2App URL

[](#generating-web2app-url)

For mobile web browsers where the user can open the Smart-ID app directly:

```
use Sk\SmartId\Util\CallbackUrlUtil;
use Sk\SmartId\Util\CallbackUrlValidator;

// Validate and create callback URL with a cryptographically random token
$callbackBase = 'https://your-app.com/callback';
$callbackResult = CallbackUrlUtil::createCallbackUrl($callbackBase);
$callbackUrl = $callbackResult['callbackUrl']; // e.g., https://your-app.com/callback?value=
$callbackToken = $callbackResult['token'];        // Store to verify the callback later

// Callback URL must be set when initiating the session
$session = $builder
    ->withCallbackUrl($callbackUrl)
    ->withAllowedInteractionsOrder([
        DeviceLinkInteraction::displayTextAndPin('Log in'),
    ])
    ->initiate();

$web2AppUrl = $session->buildWeb2AppUrl();
```

#### Overriding default values

[](#overriding-default-values)

```
$builder = $session->createDeviceLinkBuilder()
    ->withDemoEnvironment()             // override scheme for demo
    ->withLang('est')                  // override language
    ->withElapsedSeconds($elapsed);

$qrCodeUrl = $builder->buildQrCodeUrl();
```

### Examples of allowed device link interactions

[](#examples-of-allowed-device-link-interactions)

An app can support different interaction types, and a Relying Party can specify preferred interactions with or without fallback options. For device link flows, the available interaction types are limited to `displayTextAndPIN` and `confirmationMessage`. `displayTextAndPIN` is used for short text with PIN-code input, while `confirmationMessage` is used for longer text with Confirm and Cancel buttons and a second screen to enter the PIN-code.

**Example 1:** `confirmationMessage` with fallback to `displayTextAndPIN`

The RP's first choice is `confirmationMessage`; if not available, then fall back to `displayTextAndPIN`.

```
$builder->withAllowedInteractionsOrder([
    DeviceLinkInteraction::confirmationMessage('Up to 200 characters of text here..'),
    DeviceLinkInteraction::displayTextAndPin('Up to 60 characters of text here..'),
]);
```

**Example 2:** `confirmationMessage` only (no fallback)

If the interaction is not supported by the app, the process will fail if no fallback is provided.

```
$builder->withAllowedInteractionsOrder([
    DeviceLinkInteraction::confirmationMessage('Up to 200 characters of text here..'),
]);
```

Notification-based flows
------------------------

[](#notification-based-flows)

### Differences between notification-based and device link flows

[](#differences-between-notification-based-and-device-link-flows)

- **Notification-based flow** — Push notification is sent directly to the user's Smart-ID app. Requires knowing the user's identity (document number or semantics identifier) beforehand. More vulnerable to phishing; recommended to use after user identity has been established via device link flow. No QR codes needed.
- **Device link flow** — Generates QR codes or deep links. Supports anonymous authentication where the user's identity is not required beforehand. QR code must be refreshed every second.

### Notification-based authentication session

[](#notification-based-authentication-session)

#### Request parameters

[](#request-parameters-1)

- **relyingPartyUUID** — Required. UUID of the Relying Party.
- **relyingPartyName** — Required. Friendly name of the Relying Party.
- **documentNumber** or **semanticsIdentifier** — Required (one of). Identifies the user.
- **certificateLevel** — Optional. `QUALIFIED` or `ADVANCED`. Defaults to `QUALIFIED`.
- **hashAlgorithm** — Optional. Supported: `SHA-256`, `SHA-384`, `SHA-512`, `SHA3-256`, `SHA3-384`, `SHA3-512`. Defaults to `SHA-512`.
- **interactions** — Required. Array of `NotificationInteraction` objects defining the allowed interactions in order of preference.
- **nonce** — Optional. Random string, up to 30 characters. Used to override idempotent behaviour (if the same request is made within a 15-second window, the same response is returned unless a nonce is provided).
- **capabilities** — Optional. Array of capability strings.
- **requestProperties** — Optional. Set `shareMdClientIpAddress` to `true` to request the IP address of the user's device (see [Requesting IP address](#requesting-ip-address-of-users-device)).

#### Response parameters

[](#response-parameters-1)

- **sessionID** — String used to query the session status.

#### Initiating with semantics identifier

[](#initiating-with-semantics-identifier)

More info about Semantics Identifiers: [ETSI EN 319 412-1](https://www.etsi.org/deliver/etsi_en/319400_319499/31941201/01.01.00_30/en_31941201v010100v.pdf)

```
use Sk\SmartId\Notification\NotificationAuthenticationRequestBuilder;
use Sk\SmartId\Notification\NotificationInteraction;
use Sk\SmartId\Enum\CertificateLevel;
use Sk\SmartId\Model\SemanticsIdentifier;

// Create semantics identifier:
// Type: PNO (personal number), PAS (passport), IDC (national identity card)
// Country: 2-letter ISO 3166-1 alpha-2 code
$semanticsIdentifier = SemanticsIdentifier::forPerson('EE', '30303039914');
// Or from a full string:
// $semanticsIdentifier = SemanticsIdentifier::fromString('PNOEE-30303039914');

$builder = new NotificationAuthenticationRequestBuilder(
    $connector,
    '00000000-0000-4000-8000-000000000000', // relyingPartyUUID
    'DEMO',                                  // relyingPartyName
);

$session = $builder
    ->withSemanticsIdentifier($semanticsIdentifier)
    ->withCertificateLevel(CertificateLevel::QUALIFIED)
    ->withAllowedInteractionsOrder([
        NotificationInteraction::confirmationMessageAndVerificationCodeChoice('Log in to example.com'),
        NotificationInteraction::displayTextAndPin('Log in to example.com'),
    ])
    ->initiate();

// Display verification code to the user
$verificationCode = $session->getVerificationCode();

// Use session ID to poll for status
$sessionId = $session->getSessionId();
```

Jump to [Querying session status](#querying-session-status) for an example of session status polling.

#### Initiating with document number

[](#initiating-with-document-number)

```
$session = $builder
    ->withDocumentNumber('PNOLT-40504040001-MOCK-Q')
    ->withCertificateLevel(CertificateLevel::QUALIFIED)
    ->withAllowedInteractionsOrder([
        NotificationInteraction::displayTextAndPin('Log in to example.com'),
    ])
    ->initiate();

$verificationCode = $session->getVerificationCode();
$sessionId = $session->getSessionId();
```

### Examples of allowed notification-based interactions

[](#examples-of-allowed-notification-based-interactions)

Notification-based flows support additional interaction types compared to device link flows. Available types are `displayTextAndPIN`, `confirmationMessage`, and `confirmationMessageAndVerificationCodeChoice`.

**Example 1:** `confirmationMessageAndVerificationCodeChoice` with fallback to `confirmationMessage` and `displayTextAndPIN`

The RP's first choice is `confirmationMessageAndVerificationCodeChoice`; the second choice is `confirmationMessage`; the third choice is `displayTextAndPIN`.

```
$builder->withAllowedInteractionsOrder([
    NotificationInteraction::confirmationMessageAndVerificationCodeChoice('Up to 200 characters of text here...'),
    NotificationInteraction::confirmationMessage('Up to 200 characters of text here...'),
    NotificationInteraction::displayTextAndPin('Up to 60 characters of text here...'),
]);
```

**Example 2:** `confirmationMessageAndVerificationCodeChoice` only (no fallback)

Process will fail if interaction is not supported and there is no fallback.

```
$builder->withAllowedInteractionsOrder([
    NotificationInteraction::confirmationMessageAndVerificationCodeChoice('Up to 200 characters of text here...'),
]);
```

Querying session status
-----------------------

[](#querying-session-status)

### Session status response

[](#session-status-response)

The session status response includes various fields depending on whether the session has completed or is still running:

- **state** — `RUNNING` or `COMPLETE`
- **result.endResult** — Outcome of the session (see [End result values](#end-result-values) below).
- **result.documentNumber** — Document number returned when `endResult` is `OK`. Can be used in further authentication requests to target the same device.
- **signatureProtocol** — `ACSP_V2` for authentication.
- **signature** — For `ACSP_V2`: contains `value`, `serverRandom`, `userChallenge`, `flowType`, `signatureAlgorithm`, `signatureAlgorithmParameters`.
- **cert** — Certificate info: `value` (Base64-encoded X.509 DER) and `certificateLevel` (`QUALIFIED` or `ADVANCED`).
- **interactionTypeUsed** — The interaction type that was actually used for the session (e.g., `displayTextAndPIN`, `confirmationMessage`).
- **ignoredProperties** — Array of property names from the request that were not recognized by the server.
- **deviceIpAddress** — IP address of the user's device, if `requestProperties.shareMdClientIpAddress` was set to `true` and the feature is enabled for your account.

#### End result values

[](#end-result-values)

The `result.endResult` field may contain the following values:

- **`OK`** — Session completed successfully.
- **`USER_REFUSED`** — User refused the session.
- **`USER_REFUSED_CERT_CHOICE`** — User has multiple accounts and pressed Cancel on device choice screen.
- **`USER_REFUSED_DISPLAYTEXTANDPIN`** — User pressed Cancel on the `displayTextAndPIN` interaction screen.
- **`USER_REFUSED_VC_CHOICE`** — User pressed Cancel on the verification code choice screen.
- **`USER_REFUSED_CONFIRMATIONMESSAGE`** — User pressed Cancel on the `confirmationMessage` screen.
- **`USER_REFUSED_CONFIRMATIONMESSAGE_WITH_VC_CHOICE`** — User pressed Cancel on the `confirmationMessageAndVerificationCodeChoice` screen.
- **`USER_REFUSED_INTERACTION`** — User pressed Cancel on the interaction screen. `result.details` contains info about which interaction was canceled.
- **`TIMEOUT`** — User did not respond in time.
- **`DOCUMENT_UNUSABLE`** — Session could not be completed due to an issue with the document.
- **`WRONG_VC`** — User selected the wrong verification code.
- **`REQUIRED_INTERACTION_NOT_SUPPORTED_BY_APP`** — The requested interaction is not supported by the user's app.
- **`PROTOCOL_FAILURE`** — An error occurred in the signing protocol.
- **`EXPECTED_LINKED_SESSION`** — Server expected a device link session but received a notification-based session (or vice versa).
- **`SERVER_ERROR`** — Technical error occurred at the server side and the process was terminated.
- **`ACCOUNT_UNUSABLE`** — The user's Smart-ID account is unusable for this operation.

#### End result to exception mapping

[](#end-result-to-exception-mapping)

When using `SessionStatusPoller`, non-OK end results are automatically converted to typed exceptions:

End resultException`USER_REFUSED_INTERACTION``UserRefusedInteractionException``USER_REFUSED`, `USER_REFUSED_CERT_CHOICE`, `USER_REFUSED_DISPLAYTEXTANDPIN`, `USER_REFUSED_VC_CHOICE`, `USER_REFUSED_CONFIRMATIONMESSAGE`, `USER_REFUSED_CONFIRMATIONMESSAGE_WITH_VC_CHOICE``UserRefusedException``TIMEOUT``SessionTimeoutException``DOCUMENT_UNUSABLE``DocumentUnusableException``WRONG_VC``WrongVerificationCodeException``REQUIRED_INTERACTION_NOT_SUPPORTED_BY_APP``RequiredInteractionNotSupportedException``PROTOCOL_FAILURE``ProtocolFailureException``SERVER_ERROR``ServerErrorException``ACCOUNT_UNUSABLE`, `EXPECTED_LINKED_SESSION`, other`SmartIdException`> **Note:** `UserRefusedInteractionException` extends `UserRefusedException`. The poller checks for `USER_REFUSED_INTERACTION` first, so catching `UserRefusedException` after `UserRefusedInteractionException` handles all other user refusal variants.

### Polling for final session status

[](#polling-for-final-session-status)

Using `SessionStatusPoller` to poll until the session completes:

```
use Sk\SmartId\Session\SessionStatusPoller;

$poller = new SessionStatusPoller($connector);

// Poll until session completes (blocks with long polling)
$sessionStatus = $poller->pollUntilComplete($sessionId);

if ($sessionStatus->isComplete()) {
    $endResult = $sessionStatus->getResult()->getEndResult();
    // 'OK' means authentication succeeded
}
```

The poller automatically throws typed exceptions for error results (see [Exception handling](#exception-handling)).

You can configure polling parameters:

```
$poller = new SessionStatusPoller($connector);
$poller->setPollTimeoutMs(30000);  // Server-side long poll timeout (default: 30s)
$poller->setPollIntervalMs(1000);  // Interval between poll attempts (default: 1s)

// Limit the number of poll attempts
$sessionStatus = $poller->pollUntilComplete($sessionId, maxAttempts: 60);
```

### Single status query

[](#single-status-query)

For device link flows where you need to generate a fresh QR code every second, use single status queries:

```
$poller = new SessionStatusPoller($connector);

$sessionStatus = $poller->poll($sessionId);

if ($sessionStatus->isRunning()) {
    // Session still in progress — refresh QR code and poll again
} elseif ($sessionStatus->isComplete()) {
    // Proceed to validation
}
```

Or query the connector directly:

```
$sessionStatus = $connector->getSessionStatus($sessionId, timeoutMs: 1000);
```

Validating authentication response
----------------------------------

[](#validating-authentication-response)

It is critical to validate the authentication response to ensure the signature and certificate are trustworthy.

### Setting up trusted CA certificates

[](#setting-up-trusted-ca-certificates)

```
use Sk\SmartId\Validation\TrustedCACertificateStore;

// Create via SmartIdClient (OCSP revocation checking is enabled automatically)
$validator = $client->createAuthenticationResponseValidator();

// PRODUCTION — load bundled certificates
TrustedCACertificateStore::loadFromDefaults()->configureValidator($validator);

// DEMO — load test certificates (upload certs to demo OCSP first, see "Uploading certificates to demo OCSP")
// TrustedCACertificateStore::loadTestCertificates()->configureValidator($validator);

// Custom directory
// TrustedCACertificateStore::loadFromDirectory('/path/to/certs')->configureValidator($validator);

// Manual certificates
// $store = TrustedCACertificateStore::create()
//     ->addCertificate($pemEncodedCert)
//     ->addCertificateFromFile('/path/to/cert.pem.crt');
// $store->configureValidator($validator);
```

### OCSP certificate revocation checking

[](#ocsp-certificate-revocation-checking)

OCSP revocation checking is enabled automatically when creating a validator via `SmartIdClient::createAuthenticationResponseValidator()`. The checker verifies that the end-entity certificate has not been revoked by reading the OCSP responder URL from the certificate's Authority Information Access (AIA) extension.

> **Note:** For the demo environment, you must first upload your test certificates to the demo OCSP responder — see [Uploading certificates to demo OCSP](#uploading-certificates-to-demo-ocsp).

### Validating device link authentication

[](#validating-device-link-authentication)

```
use Sk\SmartId\Validation\TrustedCACertificateStore;
use Sk\SmartId\Enum\CertificateLevel;
use Sk\SmartId\Enum\SchemeName;
use Sk\SmartId\DeviceLink\DeviceLinkInteraction;

// Set up validator (demo environment — upload certs to demo OCSP first, see "Uploading certificates to demo OCSP")
$validator = $client->createAuthenticationResponseValidator();
TrustedCACertificateStore::loadTestCertificates()->configureValidator($validator);

// The interactions Base64 value must match what was sent in the original request
$interactions = [DeviceLinkInteraction::displayTextAndPin('Log in to example.com')];

// Initiate the authentication session
$session = $client->createDeviceLinkAuthentication()
    ->withRpChallenge($rpChallenge)
    ->withHashAlgorithm(HashAlgorithm::SHA512)
    ->withAllowedInteractionsOrder($interactions)
    ->initiate();

// The session now contains the pre-encoded interactions Base64 string
// This ensures the same encoding is used for both API requests and signature verification
$interactionsBase64 = $session->getInteractionsBase64();

// Validate and extract identity
$identity = $validator->validate(
    $sessionStatus,
    $rpChallenge,                             // Base64-encoded RP challenge from the original request
    'DEMO',                                   // Relying Party name
    $interactionsBase64,                      // Base64-encoded interactions JSON from the session
    requiredCertificateLevel: CertificateLevel::QUALIFIED,
    schemeName: SchemeName::DEMO, // Use SchemeName::PRODUCTION for live
);
```

The validator performs the following checks:

1. Session state is `COMPLETE` and result is `OK`
2. Signature protocol is `ACSP_V2`
3. Certificate level meets the requested level (if specified)
4. Certificate is signed by a trusted CA and within its validity period
5. Certificate basic constraints (not a CA certificate)
6. Certificate policies contain Smart-ID scheme OIDs
7. Certificate key usage includes `digitalSignature`
8. Certificate Extended Key Usage includes Smart-ID authentication or `clientAuth`
9. `signatureAlgorithmParameters` validation (hashAlgorithm, saltLength, maskGenAlgorithm, trailerField)
10. RSA-PSS signature verification against the ACSP\_V2 payload

### Validating notification-based authentication

[](#validating-notification-based-authentication)

Validation is the same as device link. The only difference is how the session was initiated — the validation step uses the same `AuthenticationResponseValidator::validate()` method.

```
$identity = $validator->validate(
    $sessionStatus,
    $session->getRpChallenge(),
    'DEMO',
    $session->getInteractionsBase64(),
    requiredCertificateLevel: CertificateLevel::QUALIFIED,
    schemeName: SchemeName::DEMO,
);
```

### Web2App flow validation

[](#web2app-flow-validation)

When using Web2App or App2App flows, the Smart-ID app redirects the user back to the Relying Party via the callback URL. The received callback URL will contain additional query parameters that must be validated.

Example callback URL for authentication:

```
https://rp.example.com/callback?value=RrKjjT4aggzu27YBddX1bQ&sessionSecretDigest=U4CKK13H1XFiyBofev9asqrzIrY5_Gszi_nL_zDKkBc&userChallengeVerifier=XtPfaGa8JnGtYrJjboooUf0KfY9sMEHrWFpSQrsUv9c

```

Validation steps:

1. Verify that the `value` query parameter matches the random value you included when creating the callback URL.
2. Verify `sessionSecretDigest` matches `Base64URL(SHA-256(Base64Decode(sessionSecret)))` where `sessionSecret` is from the session init response.
3. For authentication flows, verify `userChallengeVerifier` — its SHA-256 hash (Base64URL-encoded) must match `signature.userChallenge` from the session status response.

```
// 1. Verify session secret from callback URL
$validator->verifySessionSecret(
    $sessionSecret,        // from the original session response
    $sessionSecretDigest,  // from the callback URL query parameter
);

// 2. Verify user challenge from callback URL
$validator->verifyUserChallenge(
    $userChallengeVerifier,      // from the callback URL query parameter
    $userChallengeFromResponse,  // from session status response signature.userChallenge
);

// 3. Then proceed with standard validation — pass the callback URL for Web2App signature verification
$identity = $validator->validate(
    $sessionStatus,
    $rpChallenge,
    'DEMO',
    $interactionsBase64,
    $callbackUrl,                                 // initialCallbackUrl used in Web2App flow
    requiredCertificateLevel: CertificateLevel::QUALIFIED,
    schemeName: SchemeName::DEMO,
);
```

### Validating callback URL with CallbackUrlUtil

[](#validating-callback-url-with-callbackurlutil)

The `CallbackUrlUtil` helper simplifies creating and validating callback URLs for Web2App/App2App flows.

#### Creating a callback URL with a random token

[](#creating-a-callback-url-with-a-random-token)

```
use Sk\SmartId\Util\CallbackUrlUtil;

// Generate a callback URL with a cryptographically random token
$result = CallbackUrlUtil::createCallbackUrl('https://your-app.com/callback');
$callbackUrl = $result['callbackUrl']; // e.g., https://your-app.com/callback?value=abc123...
$token = $result['token'];             // Store this to verify the callback later

// Use the callback URL when initiating the session
$session = $builder
    ->withCallbackUrl($callbackUrl)
    ->withAllowedInteractionsOrder([...])
    ->initiate();
```

#### Validating session secret digest from callback

[](#validating-session-secret-digest-from-callback)

When the Smart-ID app redirects back to your callback URL, validate the `sessionSecretDigest` query parameter:

```
use Sk\SmartId\Util\CallbackUrlUtil;

// Throws ValidationException if digest does not match
CallbackUrlUtil::validateSessionSecretDigest(
    $sessionSecretDigest,  // from the callback URL query parameter
    $sessionSecret,        // from the original session init response
);
```

Extracting user identity
------------------------

[](#extracting-user-identity)

After successful validation, the `AuthenticationIdentity` object provides:

```
$identity->getGivenName();    // e.g., 'QUALIFIED OK1'
$identity->getSurname();      // e.g., 'TESTNUMBER'
$identity->getFullName();     // e.g., 'QUALIFIED OK1 TESTNUMBER'
$identity->getIdentityCode(); // e.g., '30303039914'
$identity->getCountry();      // e.g., 'EE'

// Additional methods for Baltic states (EE, LV, LT):
$identity->getDateOfBirth();  // DateTimeImmutable or null
$identity->getGender();       // 'M', 'F', or null
$identity->getAge();          // int or null
```

The document number can be retrieved from the session result for future requests:

```
$documentNumber = $sessionStatus->getResult()->getDocumentNumber();
```

Additional request properties
-----------------------------

[](#additional-request-properties)

### Requesting IP address of user's device

[](#requesting-ip-address-of-users-device)

For the IP address to be returned, the service provider (SK) must enable this option for your account. More info: [https://sk-eid.github.io/smart-id-documentation/rp-api/3.0.3/request\_properties.html](https://sk-eid.github.io/smart-id-documentation/rp-api/3.0.3/request_properties.html)

```
// Device link authentication with IP address sharing
$session = $builder
    ->withCertificateLevel(CertificateLevel::QUALIFIED)
    ->withAllowedInteractionsOrder([
        DeviceLinkInteraction::displayTextAndPin('Log in to example.com'),
    ])
    ->withShareMdClientIpAddress()
    ->initiate();

// After session completes, retrieve the device IP address
$sessionStatus = $poller->pollUntilComplete($session->getSessionId());
$deviceIpAddress = $sessionStatus->getDeviceIpAddress(); // IP address or null
```

The same `withShareMdClientIpAddress()` method is available on both `DeviceLinkAuthenticationRequestBuilder` and `NotificationAuthenticationRequestBuilder`.

Exception handling
------------------

[](#exception-handling)

The library provides specific exceptions for different error scenarios. All exceptions extend `SmartIdException`.

### Permanent exceptions

[](#permanent-exceptions)

These indicate client-side configuration or input errors.

- **`InvalidParametersException`** — Invalid request parameters (HTTP 400).
- **`UnauthorizedException`** — Invalid RP credentials (HTTP 401) or user not found (HTTP 403).

### User action exceptions

[](#user-action-exceptions)

These cover scenarios where user actions or inactions lead to session termination.

- **`UserRefusedException`** — User refused the operation.
- **`UserRefusedInteractionException`** — User pressed Cancel on a specific interaction screen. Extends `UserRefusedException`. Use `getInteraction()` to see which interaction was canceled (from `result.details`).
- **`SessionTimeoutException`** — User did not respond within the allowed timeframe.
- **`WrongVerificationCodeException`** — User selected the wrong verification code.
- **`RequiredInteractionNotSupportedException`** — The required interaction type is not supported by the user's app.

### User account exceptions

[](#user-account-exceptions)

- **`UserAccountException`** — Problems with the user's Smart-ID account.
    - `isNoSuitableAccount()` — No suitable account found (HTTP 471).
    - `isPersonShouldViewApp()` — User should view Smart-ID app or self-service portal (HTTP 472).
    - `isClientTooOld()` — Client-side API too old (HTTP 480).
- **`DocumentUnusableException`** — The requested document cannot be used.

### Protocol and server exceptions

[](#protocol-and-server-exceptions)

- **`ProtocolFailureException`** — An error occurred in the signing protocol.
- **`ServerErrorException`** — Technical error occurred at the Smart-ID server side.

### Validation exceptions

[](#validation-exceptions)

- **`ValidationException`** — Thrown during response validation: certificate trust, signature mismatch, etc.

### Technical exceptions

[](#technical-exceptions)

- **`TechnicalErrorException`** — Thrown for technical errors during processing (e.g., malformed responses, unexpected data formats).

### Server-side exceptions

[](#server-side-exceptions)

- **`SmartIdException`** — Smart-ID service temporarily unavailable (HTTP 5xx) or other unclassified errors.
- **`UnderMaintenanceException`** — System is under maintenance (HTTP 580). Retry the request later.
- **`SessionNotFoundException`** — Session not found (HTTP 404).

### Example of handling exceptions

[](#example-of-handling-exceptions)

```
use Sk\SmartId\Exception\SmartIdException;
use Sk\SmartId\Exception\UserRefusedException;
use Sk\SmartId\Exception\UserRefusedInteractionException;
use Sk\SmartId\Exception\SessionTimeoutException;
use Sk\SmartId\Exception\WrongVerificationCodeException;
use Sk\SmartId\Exception\UserAccountException;
use Sk\SmartId\Exception\DocumentUnusableException;
use Sk\SmartId\Exception\RequiredInteractionNotSupportedException;
use Sk\SmartId\Exception\ProtocolFailureException;
use Sk\SmartId\Exception\ServerErrorException;
use Sk\SmartId\Exception\ValidationException;
use Sk\SmartId\Exception\UnderMaintenanceException;

try {
    $sessionStatus = $poller->pollUntilComplete($sessionId);
    $identity = $validator->validate($sessionStatus, ...);
} catch (SessionTimeoutException $e) {
    // User did not respond in time
} catch (UserRefusedInteractionException $e) {
    // User refused a specific interaction — check which one
    $interaction = $e->getInteraction(); // e.g., 'displayTextAndPIN'
} catch (UserRefusedException $e) {
    // User refused the operation (covers USER_REFUSED and all USER_REFUSED_* variants)
} catch (WrongVerificationCodeException $e) {
    // User selected wrong verification code
} catch (DocumentUnusableException $e) {
    // Document is unusable for this operation
} catch (RequiredInteractionNotSupportedException $e) {
    // Required interaction not supported by user's app
} catch (UserAccountException $e) {
    if ($e->isNoSuitableAccount()) {
        // No suitable Smart-ID account
    } elseif ($e->isPersonShouldViewApp()) {
        // User should check Smart-ID app
    } elseif ($e->isClientTooOld()) {
        // Client-side API too old
    }
} catch (ProtocolFailureException $e) {
    // Protocol failure — retry may help
} catch (ServerErrorException $e) {
    // Smart-ID server error — retry later
} catch (ValidationException $e) {
    // Authentication response validation failed — do not trust!
} catch (UnderMaintenanceException $e) {
    // System is under maintenance (HTTP 580) — retry later
} catch (SmartIdException $e) {
    // General Smart-ID error (includes ACCOUNT_UNUSABLE, EXPECTED_LINKED_SESSION, HTTP 5xx)
}
```

Logging
-------

[](#logging)

The SDK supports optional [PSR-3](https://www.php-fig.org/psr/psr-3/) logging. Pass any `LoggerInterface` implementation (e.g. [Monolog](https://github.com/Seldaek/monolog)) to `SmartIdClient` and `AuthenticationResponseValidator`. If no logger is provided, a `NullLogger` is used and no output is produced.

### What is logged

[](#what-is-logged)

ComponentLevelWhat`SmartIdRestConnector``debug`Outgoing HTTP request method and URL`SmartIdRestConnector``debug`Successful response status code`SmartIdRestConnector``warning`Error response status code`SessionStatusPoller``debug`Each poll attempt (session ID)`SessionStatusPoller``info`Session completed (session ID, end result)`SessionStatusPoller``warning`Authentication failed (end result: TIMEOUT, USER\_REFUSED, etc.)`SessionStatusPoller``warning`Polling timed out (session ID, attempts)Request builders`info`Session initiationRequest builders`debug`Session initiated (session ID)`AuthenticationResponseValidator``info`Validation start and success`AuthenticationResponseValidator``error`Validation failed (error message)`AuthenticationResponseValidator``debug`Each validation step (trust chain, constraints, policies, signature)`OcspCertificateRevocationChecker``debug`OCSP request/response and success`OcspCertificateRevocationChecker``warning`OCSP check failure> **Note:** The SDK never logs request/response bodies, personal data, or secrets. Only metadata such as URLs, status codes, and session IDs are logged.

### Using with SmartIdClient

[](#using-with-smartidclient)

The logger is passed as the last constructor parameter and automatically propagated to the connector, session status poller, and request builders.

```
use Psr\Log\LoggerInterface;
use Sk\SmartId\SmartIdClient;
use Sk\SmartId\Ssl\SslPinnedPublicKeyStore;

// Example with Monolog
$logger = new \Monolog\Logger('smart-id');
$logger->pushHandler(new \Monolog\Handler\StreamHandler('php://stderr', \Monolog\Level::Debug));

$client = new SmartIdClient(
    relyingPartyUUID: '00000000-0000-4000-8000-000000000000',
    relyingPartyName: 'DEMO',
    hostUrl: 'https://sid.demo.sk.ee/smart-id-rp/v3',
    sslPinnedKeys: SslPinnedPublicKeyStore::loadDemo(),
    logger: $logger,
);
```

###  Health Score

57

—

FairBetter than 98% of packages

Maintenance69

Regular maintenance activity

Popularity50

Moderate usage in the ecosystem

Community21

Small or concentrated contributor base

Maturity72

Established project with proven stability

 Bus Factor1

Top contributor holds 98.3% 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 ~153 days

Recently: every ~297 days

Total

20

Last Release

406d ago

Major Versions

v1.5.2 → 2.02021-04-07

PHP version history (5 changes)v1.0PHP &gt;=5.6

v1.5.1PHP &gt;=7.0.7

2.0PHP &gt;=7.2

2.1.x-devPHP &gt;=7.3

2.3PHP &gt;=7.4

### Community

Maintainers

![](https://www.gravatar.com/avatar/6db2adfebb303ffae898927bb826f25f3b2822b3a3612cc7f51a7fb6a115b751?d=identicon)[aasaru](/maintainers/aasaru)

![](https://www.gravatar.com/avatar/5a3e016145e867a5f6597eade80e6c56e9d721515a444e2715c810f94637a81d?d=identicon)[sk-eid](/maintainers/sk-eid)

---

Top Contributors

[![MartinAtStagnation](https://avatars.githubusercontent.com/u/228001242?v=4)](https://github.com/MartinAtStagnation "MartinAtStagnation (59 commits)")[![martiina](https://avatars.githubusercontent.com/u/9255919?v=4)](https://github.com/martiina "martiina (1 commits)")

---

Tags

apismart-idrelyingparty

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/sk-id-solutions-smart-id-php-client/health.svg)

```
[![Health](https://phpackages.com/badges/sk-id-solutions-smart-id-php-client/health.svg)](https://phpackages.com/packages/sk-id-solutions-smart-id-php-client)
```

###  Alternatives

[culqi/culqi-php

Cliente Culqi API para PHP

41356.8k1](/packages/culqi-culqi-php)[comgate/sdk

Comgate PHP SDK

13327.8k](/packages/comgate-sdk)[satispay/gbusiness-api-php-sdk

Satispay GBusiness API PHP SDK

19198.0k4](/packages/satispay-gbusiness-api-php-sdk)[optiosteam/payconiq-client-php

Payconiq API client library for PHP developed by Optios.

1273.4k](/packages/optiosteam-payconiq-client-php)[openpesa/pesa

Pesa PHP SDK

291.3k2](/packages/openpesa-pesa)

PHPackages © 2026

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