PHPackages                             jitso/laravel-snelstart - 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. jitso/laravel-snelstart

ActiveLibrary[API Development](/categories/api)

jitso/laravel-snelstart
=======================

Laravel package for the Snelstart B2B API v2 with Eloquent-like models

v1.2.2(2mo ago)018↑733.3%MITPHPPHP ^8.2

Since Mar 12Pushed 2mo agoCompare

[ Source](https://github.com/JitsoMaatwerkSoftware/laravel-snelstart)[ Packagist](https://packagist.org/packages/jitso/laravel-snelstart)[ RSS](/packages/jitso-laravel-snelstart/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (5)Versions (7)Used By (0)

Laravel Snelstart
=================

[](#laravel-snelstart)

A Laravel package for the [Snelstart B2B API v2](https://b2bapi.snelstart.nl/v2) with an Eloquent-like interface. Query, create, update, and delete Snelstart resources using familiar Laravel syntax.

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

[](#requirements)

- PHP 8.2+
- Laravel 11 or 12

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

[](#installation)

```
composer require jitso/laravel-snelstart
```

The service provider and facade are auto-discovered.

Configuration
-------------

[](#configuration)

Publish the config file:

```
php artisan vendor:publish --tag=snelstart-config
```

Add the following to your `.env`:

```
SNELSTART_SUBSCRIPTION_KEY=your-subscription-key
SNELSTART_CLIENT_KEY=your-oauth2-client-id
SNELSTART_CLIENT_SECRET=your-oauth2-client-secret
```

### Authentication type

[](#authentication-type)

The package supports two authentication methods. Set `SNELSTART_AUTH_TYPE` in your `.env`:

**OAuth2 (default)** -- uses `client_credentials` grant with client key + secret:

```
SNELSTART_AUTH_TYPE=oauth
SNELSTART_CLIENT_KEY=your-client-id
SNELSTART_CLIENT_SECRET=your-client-secret
```

**Client Key** -- uses the simpler `clientkey` grant with only a client key:

```
SNELSTART_AUTH_TYPE=clientkey
SNELSTART_CLIENT_KEY=your-client-key
```

### All config options

[](#all-config-options)

KeyEnv variableDefault`subscription_key``SNELSTART_SUBSCRIPTION_KEY`—`authentication_type``SNELSTART_AUTH_TYPE``oauth``client_key``SNELSTART_CLIENT_KEY`—`client_secret``SNELSTART_CLIENT_SECRET`— (only for `oauth`)`base_url``SNELSTART_BASE_URL``https://b2bapi.snelstart.nl/v2``token_url``SNELSTART_TOKEN_URL``https://auth.snelstart.nl/b2b/token``cache_token``SNELSTART_CACHE_TOKEN``true`Usage
-----

[](#usage)

### Basic CRUD

[](#basic-crud)

```
use Jitso\LaravelSnelstart\Models\Artikel;

// Get all
$artikelen = Artikel::all();

// Find by ID
$artikel = Artikel::find('550e8400-e29b-41d4-a716-446655440000');

// Create
$artikel = Artikel::create([
    'artikelcode' => 'PROD-001',
    'omschrijving' => 'Voorbeeld product',
    'verkoopprijs' => 29.95,
]);

// Update
$artikel->update(['omschrijving' => 'Nieuwe omschrijving']);

// Delete
$artikel->delete();
```

### Query builder (OData)

[](#query-builder-odata)

Resources with OData support can be queried with a familiar builder syntax. Operators are automatically translated to OData filter expressions.

```
use Jitso\LaravelSnelstart\Models\Relatie;

// Where clause (translates to $filter=naam eq 'Jitso')
$relaties = Relatie::where('naam', 'Jitso')->get();

// Comparison operators
$relaties = Relatie::where('krediettermijn', '>', 30)->get();

// Contains / starts with / ends with
$relaties = Relatie::query()
    ->whereContains('naam', 'holding')
    ->get();

// Pagination with $top and $skip
$relaties = Relatie::take(10)->skip(20)->get();

// Get the first result
$relatie = Relatie::where('naam', 'Jitso')->first();

// Combine multiple filters (joined with 'and')
$artikelen = Artikel::where('isNonActief', false)
    ->where('verkoopprijs', '>', 10)
    ->take(25)
    ->get();

// Raw OData filter
$artikelen = Artikel::filter("contains(omschrijving, 'test')")->get();

// Lazy pagination (automatically fetches all pages)
$alleRelaties = Relatie::query()->paginate(500);
```

**Supported operators:** `=`, `!=`, `>`, `>=`, ` 'Jitso B.V.'],
    ['email' => 'info@jitso.nl', 'telefoon' => '0612345678'],
);

// Find by attributes, update if found, create if not
$artikel = Artikel::updateOrCreate(
    ['artikelcode' => 'PROD-001'],
    ['omschrijving' => 'Updated product', 'verkoopprijs' => 39.95],
);

// Get an unsaved instance if not found (useful for forms)
$artikel = Artikel::firstOrNew(['artikelcode' => 'NIEUW']);
$artikel->omschrijving = 'Handmatig ingevuld';
$artikel->save();

// Find by ID with fallback to empty instance
$artikel = Artikel::findOrNew('possibly-invalid-uuid');

// Also works via the query builder
$relatie = Relatie::where('naam', 'Jitso B.V.')
    ->firstOrCreate(['email' => 'info@jitso.nl']);

$artikel = Artikel::where('artikelcode', 'PROD-001')
    ->updateOrCreate(['verkoopprijs' => 49.95]);
```

### Sub-resources

[](#sub-resources)

Some models expose related resources as methods:

```
$relatie = Relatie::find('uuid');

$inkoopboekingen = $relatie->inkoopboekingen();
$verkoopboekingen = $relatie->verkoopboekingen();
$machtigingen = $relatie->doorlopendeIncassomachtigingen();

// Custom fields (read & update)
$fields = $relatie->customFields();
$relatie->updateCustomFields([
    ['name' => 'MijnVeld', 'value' => 'waarde'],
]);
```

```
$artikel = Artikel::find('uuid');

$fields = $artikel->customFields();
$artikel->updateCustomFields([...]);

// Article price agreements
$afspraken = Artikel::prijsafspraken();
$afspraken = Artikel::prijsafsprakenQuery()
    ->where('artikelCode', 'PROD-001')
    ->get();
```

### Special models

[](#special-models)

**CompanyInfo** -- singleton resource:

```
use Jitso\LaravelSnelstart\Models\CompanyInfo;

$info = CompanyInfo::get();
$info->update(['bedrijfsnaam' => 'Nieuwe Naam B.V.']);
```

**Rapportage:**

```
use Jitso\LaravelSnelstart\Models\Rapportage;

$balans = Rapportage::kolommenbalans();
$periode = Rapportage::periodebalans(['boekjaar' => 2025]);
```

**Documents:**

```
use Jitso\LaravelSnelstart\Models\Document;

$doc = Document::find('uuid');
$docs = Document::forParent('VerkoopBoeking', 'parent-uuid');
$doc = Document::createForType('VerkoopBoeking', [
    'parentIdentifier' => 'parent-uuid',
    'fileName' => 'factuur.pdf',
    'content' => base64_encode($pdfContent),
]);
```

**Verkooporder processtatus:**

```
use Jitso\LaravelSnelstart\Models\Verkooporder;

$order = Verkooporder::find('uuid');
$order->updateProcesStatus('Uitgevoerd');
```

**Inkoopboeking -- UBL &amp; attachment import:**

```
use Jitso\LaravelSnelstart\Models\Inkoopboeking;

Inkoopboeking::createFromUbl('factuur.xml', $xmlContent);
Inkoopboeking::createFromAttachment('scan.pdf', base64_encode($pdf));
```

**BTW aangifte:**

```
use Jitso\LaravelSnelstart\Models\BtwAangifte;

$aangifte = BtwAangifte::find('uuid');
$aangifte->externAangeven(true);
```

**Verkoopfactuur -- UBL export:**

```
use Jitso\LaravelSnelstart\Models\Verkoopfactuur;

$factuur = Verkoopfactuur::find('uuid');
$ubl = $factuur->ubl();
```

### Using the Facade

[](#using-the-facade)

For direct API access without models:

```
use Jitso\LaravelSnelstart\Facades\Snelstart;

$response = Snelstart::get('artikelen', ['$top' => 10]);
$response = Snelstart::post('artikelen', ['artikelcode' => 'NEW']);
$response = Snelstart::put('artikelen/uuid', [...]);
Snelstart::delete('artikelen/uuid');
```

### Validation

[](#validation)

Write models validate attributes at runtime. Each model defines which fields are `$fillable` (allowed) and which are `$required` (mandatory on create). A `ValidationException` is thrown when constraints are violated.

```
use Jitso\LaravelSnelstart\Models\Verkoopboeking;
use Jitso\LaravelSnelstart\Exceptions\ValidationException;

try {
    // Missing required fields → ValidationException
    Verkoopboeking::create([
        'omschrijving' => 'Test',
    ]);
} catch (ValidationException $e) {
    // "Verkoopboeking: missing required fields: factuurnummer, klant, boekingsregels"
    $e->errors; // ['factuurnummer' => ['This field is required.'], ...]
}

try {
    // Unknown field → ValidationException
    Verkoopboeking::create([
        'factuurnummer' => 'F-001',
        'klant' => ['id' => '...'],
        'boekingsregels' => [...],
        'nietBestaandVeld' => 'oops',
    ]);
} catch (ValidationException $e) {
    // "Verkoopboeking: unknown fields: nietBestaandVeld"
}
```

Validation runs on both `create()` and `update()`. The `update()` method only checks fillable (not required), since partial updates are common.

All models expose their fields via `@property` PHPDoc annotations, so your IDE will autocomplete available field names when constructing arrays for `create()` and `update()`.

### Error handling

[](#error-handling)

The package throws specific exceptions based on HTTP status codes:

```
use Jitso\LaravelSnelstart\Exceptions\AuthenticationException;
use Jitso\LaravelSnelstart\Exceptions\NotFoundException;
use Jitso\LaravelSnelstart\Exceptions\ValidationException;
use Jitso\LaravelSnelstart\Exceptions\SnelstartException;

try {
    $artikel = Artikel::find('non-existent-uuid');
} catch (NotFoundException $e) {
    // 404
} catch (ValidationException $e) {
    // 400 or local validation -- access field errors via $e->errors
} catch (AuthenticationException $e) {
    // 401 / 403
} catch (SnelstartException $e) {
    // Any other API error
}
```

Available models
----------------

[](#available-models)

Each model only exposes the methods its API endpoint actually supports. Your IDE autocompletion will only show relevant methods.

CapabilityTraitsMethodsRead`CanRead``all()`, `find()`, `findOrNew()`, `query()`, `where()`, `take()`, `skip()`, `filter()`Create`CanCreate``create()`, `firstOrCreate()`, `firstOrNew()`Update`CanUpdate``update()`Delete`CanDelete``delete()`Upsert`CanUpsert``updateOrCreate()`### Full CRUD + OData

[](#full-crud--odata)

`Artikel`, `Bankboeking`, `Kasboeking`, `Relatie`, `Verkoopboeking`, `Verkooporder`, `Offerte`

### Full CRUD

[](#full-crud)

`Kostenplaats`, `Inkoopboeking`, `Memoriaalboeking`

### Read + Create

[](#read--create)

`Grootboek`

### Read-only + OData

[](#read-only--odata)

`GrootboekMutatie`, `Inkoopfactuur`, `Prijsafspraak`, `ArtikelPrijsafspraak`, `Verkoopfactuur`, `BtwAangifte`, `Actieprijzen`, `VatRate`, `VatRateDefinition`

### Read-only

[](#read-only)

`ArtikelOmzetgroep`, `Dagboek`, `Land`, `Verkoopordersjabloon`, `BtwTarief`

### Special

[](#special)

`CompanyInfo`, `Document`, `Rapportage`, `Bankafschriftbestand`, `Authorization`, `Echo`

License
-------

[](#license)

MIT

###  Health Score

41

—

FairBetter than 89% of packages

Maintenance88

Actively maintained with recent releases

Popularity9

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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 ~0 days

Total

6

Last Release

61d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/7e5f3ce0acfac99adf1ce6bf3b435ef9403edfe96c6d3d9db52a4da9d3051d12?d=identicon)[Doanii](/maintainers/Doanii)

![](https://www.gravatar.com/avatar/4962f2226d42ef0aee8e199ad38aa04ca8b559d19f621ad221ef6bdad0ad1f75?d=identicon)[Jitsosoftware](/maintainers/Jitsosoftware)

---

Top Contributors

[![Doanii](https://avatars.githubusercontent.com/u/119493396?v=4)](https://github.com/Doanii "Doanii (10 commits)")

---

Tags

apilaravelb2bsnelstartboekhouding

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/jitso-laravel-snelstart/health.svg)

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

###  Alternatives

[andreaselia/laravel-api-to-postman

Generate a Postman collection automatically from your Laravel API

1.0k586.2k3](/packages/andreaselia-laravel-api-to-postman)[essa/api-tool-kit

set of tools to build an api with laravel

52680.5k](/packages/essa-api-tool-kit)[resend/resend-laravel

Resend for Laravel

1191.4M6](/packages/resend-resend-laravel)[dragon-code/laravel-json-response

Automatically always return a response in JSON format

1118.6k1](/packages/dragon-code-laravel-json-response)[api-platform/laravel

API Platform support for Laravel

59126.4k6](/packages/api-platform-laravel)[simplestats-io/laravel-client

Client for SimpleStats!

4515.5k](/packages/simplestats-io-laravel-client)

PHPackages © 2026

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