PHPackages                             hyperlab/laravel-dimona - 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. hyperlab/laravel-dimona

ActiveLibrary

hyperlab/laravel-dimona
=======================

Interact with Dimona in Laravel

2.3.1(2mo ago)035[4 PRs](https://github.com/hyperlab-be/laravel-dimona/pulls)MITPHPPHP ^8.3CI failing

Since Jun 19Pushed 2mo agoCompare

[ Source](https://github.com/hyperlab-be/laravel-dimona)[ Packagist](https://packagist.org/packages/hyperlab/laravel-dimona)[ Docs](https://github.com/hyperlab/laravel-dimona)[ GitHub Sponsors](https://github.com/Hyperlab)[ RSS](/packages/hyperlab-laravel-dimona/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (26)Versions (22)Used By (0)

Interact with Dimona in Laravel
===============================

[](#interact-with-dimona-in-laravel)

[![Latest Version on Packagist](https://camo.githubusercontent.com/42ec8dc2127d81ae54704673782be36f16fe5e381bbde97bbd074ae69fc81d14/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f68797065726c61622f6c61726176656c2d64696d6f6e612e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/hyperlab/laravel-dimona)[![GitHub Tests Action Status](https://camo.githubusercontent.com/19692439f12aa2850048c8044cc8f283d9125cbcf67caa654c2449ae22584ae7/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f68797065726c61622f6c61726176656c2d64696d6f6e612f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/hyperlab/laravel-dimona/actions?query=workflow%3Arun-tests+branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/a90fdf37669ab17b1c2bdedd50e7129e05dbd6729e61cda8ecb8323391c250e5/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f68797065726c61622f6c61726176656c2d64696d6f6e612f6669782d7068702d636f64652d7374796c652d6973737565732e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652532307374796c65267374796c653d666c61742d737175617265)](https://github.com/hyperlab/laravel-dimona/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/6a27b37d1f133eaecc49caace46ae081ddb5c2abc8a594f36c1fce6bfe9a3941/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f68797065726c61622f6c61726176656c2d64696d6f6e612e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/hyperlab/laravel-dimona)

This package provides an easy way to interact with the Dimona API in Laravel applications.

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require hyperlab/laravel-dimona
```

You can publish and run the migrations with:

```
php artisan vendor:publish --tag="laravel-dimona-migrations"
php artisan migrate
```

You can publish the config file with:

```
php artisan vendor:publish --tag="laravel-dimona-config"
```

This is the contents of the published config file:

```
return [

    /*
    |--------------------------------------------------------------------------
    | API Endpoints
    |--------------------------------------------------------------------------
    |
    | The endpoints for the Dimona API.
    |
    */

    'endpoint' => env('DIMONA_ENDPOINT', 'https://services.socialsecurity.be/REST/dimona/v2'),

    'oauth_endpoint' => env('DIMONA_OAUTH_ENDPOINT', 'https://services.socialsecurity.be/REST/oauth/v5/token'),

    /*
    |--------------------------------------------------------------------------
    | Default Client
    |--------------------------------------------------------------------------
    |
    | The default client to use when no client is specified.
    |
    */

    'default_client' => env('DIMONA_DEFAULT_CLIENT', 'default'),

    /*
    |--------------------------------------------------------------------------
    | API Clients
    |--------------------------------------------------------------------------
    |
    | Configure multiple API clients with different credentials.
    | Each client has its own client_id, private_key_path, and enterprise_number.
    |
    */

    'clients' => [

        'default' => [
            'client_id' => env('DIMONA_CLIENT_ID'),
            'private_key_path' => env('DIMONA_PRIVATE_KEY_PATH'),
        ],

        // Add more clients as needed:
        // 'client2' => [
        //     'client_id' => env('DIMONA_CLIENT2_ID'),
        //     'private_key_path' => env('DIMONA_CLIENT2_PRIVATE_KEY_PATH'),
        // ],

    ],

];
```

Usage
-----

[](#usage)

### Configuration

[](#configuration)

First, configure your Dimona API credentials in the `.env` file:

```
DIMONA_CLIENT_ID=your-client-id
DIMONA_PRIVATE_KEY_PATH=/path/to/your/private-key.pem

```

For multiple clients, you can configure them in the `config/dimona.php` file:

```
'clients' => [
    'default' => [
        'client_id' => env('DIMONA_CLIENT_ID'),
        'private_key_path' => env('DIMONA_PRIVATE_KEY_PATH'),
    ],
    'client2' => [
        'client_id' => env('DIMONA_CLIENT2_ID'),
        'private_key_path' => env('DIMONA_CLIENT2_PRIVATE_KEY_PATH'),
    ],
],
```

### Basic Usage

[](#basic-usage)

Call the `declare` method on the `Dimona` facade with a period and collection of `EmploymentData` objects.

```
use Carbon\CarbonImmutable;
use Carbon\CarbonPeriodImmutable;
use Hyperlab\Dimona\Data\EmploymentData;
use Illuminate\Support\Collection;

$period = CarbonPeriodImmutable::dates(
    CarbonImmutable::startOfWeek(),
    CarbonImmutable::endOfWeek(),
);

$employments = new Collection([
    new EmploymentData(...),
    new EmploymentData(...),
    new EmploymentData(...),
]);

// Declare a Dimona
Dimona::declare($period, $employments);

// Use a specific client
Dimona::client('default')->declare($period, $employments);
```

Use the `HasDimonaPeriods` trait in your employment model:

```
use Hyperlab\Dimona\HasDimonaPeriods;

class Employment extends Model
{
    use HasDimonaPeriods;
}
```

How It Works
------------

[](#how-it-works)

### Overview

[](#overview)

The Laravel Dimona package integrates with the **Belgian Dimona API** (Declaration of Immediate Employment), which is required by Belgian law to declare worker employment periods to social security authorities. The package provides a complete, production-ready solution with automatic retries, smart syncing, and comprehensive error handling.

### Architecture

[](#architecture)

The package is built around several key concepts:

#### **Models**

[](#models)

- **DimonaPeriod**: Represents a work period that needs to be declared to Dimona

    - Tracks employer, worker, dates, hours, location, and worker type
    - States: `New`, `Outdated`, `Pending`, `Accepted`, `AcceptedWithWarning`, `Refused`, `Waiting`, `Cancelled`, `Failed`
- **DimonaDeclaration**: Audit trail of API declarations (In/Update/Cancel)

    - Belongs to a DimonaPeriod
    - Stores payload, reference, state, and anomalies from the API
- **DimonaWorkerTypeException**: Stores worker type exceptions

    - When the API rejects a flexi/student declaration, the package automatically stores an exception and retries with a different worker type

#### **Services**

[](#services)

- **DimonaApiClient**: Handles HTTP communication with the Dimona API

    - OAuth2 authentication using JWT with RSA private key
    - Automatic token caching for efficiency
- **DimonaService**: High-level service for period operations

    - Creates, updates, and cancels dimona periods
    - Syncs declaration states with the API
- **DimonaPayloadBuilder**: Builds API payloads for different declaration types and worker types

### Main Workflow

[](#main-workflow)

When you call `Dimona::declare()`, the package dispatches the `SyncDimonaPeriodsJob` which orchestrates a **7-phase workflow**:

#### **Phase 1: Sync Pending Declarations**

[](#phase-1-sync-pending-declarations)

- Queries all periods with `Pending` or `Waiting` states
- Calls the Dimona API to check the status of each declaration
- Updates period and declaration states based on API responses
- Handles worker type exceptions when the API rejects specific worker types

#### **Phase 2: Compute Expected Periods**

[](#phase-2-compute-expected-periods)

Transforms raw employment data into expected Dimona periods:

- Groups employments by joint commission, worker type, and start date
- Applies different rules per worker type:
    - **Flexi**: One period per employment with exact start/end times
    - **Student**: Aggregates hours for the day, tracks location changes
    - **Other**: Aggregates employments for the start date
- Applies worker type exceptions (overrides based on past API responses)

#### **Phase 3: Sync Expectations with Actual Periods**

[](#phase-3-sync-expectations-with-actual-periods)

Smart matching algorithm to minimize API calls:

- For each expected period, the package tries to:
    1. Find an exact match (already synced) → no action needed
    2. Update a linked period (marks as `Outdated`) → sends update declaration
    3. Reuse an unlinked period → links it to the employment
    4. Create a new period (state: `New`) → sends in declaration
- Detaches deleted employments from periods

#### **Phase 4: Cancel Unwanted Periods**

[](#phase-4-cancel-unwanted-periods)

- Cancels periods without employments
- Cancels periods with `AcceptedWithWarning` state (if configured)

#### **Phase 5: Update Declarations**

[](#phase-5-update-declarations)

Sends update declarations for periods with `Outdated` state

#### **Phase 6: Create Declarations**

[](#phase-6-create-declarations)

Sends "in" declarations for periods with `New` state

#### **Phase 7: Backoff &amp; Retry**

[](#phase-7-backoff--retry)

If any periods are still pending, re-dispatches the job with exponential backoff:

- 1st retry: 1 second
- 2nd retry: 60 seconds
- 3rd retry: 3600 seconds (1 hour)

### Worker Type Handling

[](#worker-type-handling)

The package automatically handles Belgian worker type requirements:

- **Flexi workers**: Must declare exact start/end times for each shift
- **Student workers**: Can aggregate hours per day
- **Other workers**: Standard declarations

When the API rejects a declaration due to worker type issues (e.g., "flexi requirements not met"), the package:

1. Stores a `DimonaWorkerTypeException` for that worker
2. Automatically marks the period as `Outdated`
3. Retries with the correct worker type
4. Caches the exception to avoid future errors

### State Management

[](#state-management)

The package uses a robust state machine to track the lifecycle of periods:

```
New → Pending → Accepted
                   ↓
                AcceptedWithWarning
                   ↓
                Cancelled

New → Outdated → Pending → Accepted

Pending → Refused
Pending → Failed

```

Each state transition is logged, and events are fired for integration with your application logic.

### Key Features

[](#key-features)

- **Smart Syncing**: Minimizes API calls by intelligently matching expected periods with existing ones
- **Automatic Retries**: Exponential backoff for pending declarations ensures eventual consistency
- **Multi-Client Support**: Manage multiple API credentials for different employers
- **Audit Trail**: Complete history of all declarations for compliance
- **Worker Type Resolution**: Automatic handling of type mismatches and exceptions
- **Job-Based**: Asynchronous processing with Laravel queue support
- **OAuth2 Authentication**: Secure JWT-based authentication with token caching
- **Event-Driven**: Dispatches events for integration with application logic

### Example Flow

[](#example-flow)

```
// 1. You declare employments
Dimona::declare($employerEnterpriseNumber, $workerSSN, $period, $employments);

// 2. Job dispatched → Phase 2: Compute expected periods
// Creates DimonaPeriod with state: New

// 3. Phase 6: Create declarations
// Sends "in" declaration to API
// Period state: New → Pending

// 4. Phase 7: Backoff & retry (1 second later)
// Phase 1: Sync pending declarations
// API returns: Accepted
// Period state: Pending → Accepted

// 5. Events fired:
// - DimonaPeriodCreated
// - DimonaPeriodStateUpdated (New → Pending)
// - DimonaPeriodStateUpdated (Pending → Accepted)
```

Events
------

[](#events)

This package dispatches the following events:

### DimonaPeriodCreated

[](#dimonaperiodcreated)

This event is dispatched when a new DimonaPeriod is created.

```
use Hyperlab\Dimona\Events\DimonaPeriodCreated;

// Listen for the event
Event::listen(function (DimonaPeriodCreated $event) {
    $dimonaPeriod = $event->dimonaPeriod;
    // Your code here
});
```

### DimonaPeriodStateUpdated

[](#dimonaperiodstateupdated)

This event is dispatched when a DimonaPeriod's state is updated.

```
use Hyperlab\Dimona\Events\DimonaPeriodStateUpdated;

// Listen for the event
Event::listen(function (DimonaPeriodStateUpdated $event) {
    $dimonaPeriod = $event->dimonaPeriod;
    // Your code here
});
```

Testing
-------

[](#testing)

```
composer test
```

### Mocking the Dimona API

[](#mocking-the-dimona-api)

For testing code that interacts with the Dimona API, you can use the `MockDimonaApiClient` class:

```
use Hyperlab\Dimona\Tests\Mocks\MockDimonaApiClient;

// Create a mock client
$mock = new MockDimonaApiClient();

// Mock responses
$mock
    ->mockCreateDeclaration('test-reference')
    ->mockGetDeclaration('test-reference', 'A')
    ->register();

// Now any code that uses DimonaApiClient will use your mock
```

See the [mock documentation](tests/Mocks/README.md) for more details.

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

Please review [our security policy](../../security/policy) on how to report security vulnerabilities.

Credits
-------

[](#credits)

- [Hyperlab](https://github.com/hyperlab-be)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

44

—

FairBetter than 92% of packages

Maintenance87

Actively maintained with recent releases

Popularity9

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity61

Established project with proven stability

 Bus Factor1

Top contributor holds 88.2% 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 ~18 days

Recently: every ~32 days

Total

16

Last Release

65d ago

Major Versions

1.0.8 → 2.0.02025-10-23

### Community

Maintainers

![](https://www.gravatar.com/avatar/a7cd1a8c7cc7975e2168c34b67c0674f4f6deda6e085630b7812f339a184e278?d=identicon)[hyperlab](/maintainers/hyperlab)

---

Top Contributors

[![michielkempen](https://avatars.githubusercontent.com/u/14795113?v=4)](https://github.com/michielkempen "michielkempen (30 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (2 commits)")[![liesvermeer](https://avatars.githubusercontent.com/u/257737906?v=4)](https://github.com/liesvermeer "liesvermeer (2 commits)")

---

Tags

laravelhyperlablaravel-dimona

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/hyperlab-laravel-dimona/health.svg)

```
[![Health](https://phpackages.com/badges/hyperlab-laravel-dimona/health.svg)](https://phpackages.com/packages/hyperlab-laravel-dimona)
```

###  Alternatives

[vormkracht10/laravel-mails

Laravel Mails can collect everything you might want to track about the mails that has been sent by your Laravel app.

24149.7k](/packages/vormkracht10-laravel-mails)[spatie/laravel-prometheus

Export Laravel metrics to Prometheus

2651.3M6](/packages/spatie-laravel-prometheus)[hydrat/filament-table-layout-toggle

Filament plugin adding a toggle button to tables, allowing user to switch between Grid and Table layouts.

6292.3k1](/packages/hydrat-filament-table-layout-toggle)[scalar/laravel

Render your OpenAPI-based API reference

6183.9k2](/packages/scalar-laravel)[ralphjsmit/laravel-helpers

A package containing handy helpers for your Laravel-application.

13704.6k2](/packages/ralphjsmit-laravel-helpers)[musahmusah/laravel-multipayment-gateways

A Laravel Package that makes implementation of multiple payment Gateways endpoints and webhooks seamless

852.2k1](/packages/musahmusah-laravel-multipayment-gateways)

PHPackages © 2026

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