Download the PHP package beckonbilling/api-client without Composer
On this page you can find all versions of the php package beckonbilling/api-client. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download beckonbilling/api-client
More information about beckonbilling/api-client
Files in beckonbilling/api-client
Package api-client
Short Description Official PHP client for the Beckon Billing REST API (v1).
License MIT
Homepage https://github.com/petarbeck/beckonbilling-api-client
Informations about the package api-client
Beckon Billing API client (PHP)
The official PHP client for the Beckon Billing
REST API (v1) - a small, typed, idiomatic wrapper over the public
/api/v1 surface: customers, article categories, articles, quotes, orders, outbound
invoices and recurring invoices, the read-only units and document-templates
vocabularies, plus user-token authentication.
- PSR-4 / PHP
>=8.2, no framework required. - Bring your own HTTP client - any PSR-18 client works and is auto-discovered.
- Typed exceptions you can branch on with a stable
error.key. - The canonical API contract lives in
openapi.yaml(import it into Postman/Insomnia). Building AI tooling on top? SeeAGENTS.md.
This is a thin, open-source HTTP wrapper - it holds no secrets and no server code. You still need a valid API token to do anything.
Installation
You also need any PSR-18 HTTP client + PSR-17 factories. If you don't already have one, add Guzzle (auto-discovered):
Quick start
Authentication
Every request sends Authorization: Bearer <token>. There are two token
flavours - both authorise through the same per-feature model:
Organisation tokens
Created in the portal under Firma -> API-Zugriff. Bound to one organisation;
carry an explicit permission grant + the send/bank capabilities. Pass the
bbp_... token as token.
User tokens (app sign-in)
Mint a token from email + password - no portal visit:
If two-factor authentication is enabled, login() throws an
AuthenticationException whose getErrorKey() is tfa_required until you pass
a code:
Organisation scoping
Set a default organisation in the config, or override per call:
A user token with exactly one organisation may omit it entirely.
Resources
| Property | Entity | Feature |
|---|---|---|
$client->customers |
Customers | customers |
$client->articleCategories |
Article categories | articles |
$client->articles |
Articles | articles |
$client->units |
Units (read-only) | none - any valid token |
$client->documentTemplates |
Document templates (read-only) | quotes / outbound_invoices |
$client->quotes |
Quotes | quotes |
$client->orders |
Orders (Auftraege) - no internal rate, no profitability, no sub-routes | orders |
$client->outboundInvoices |
Outbound invoices | outbound_invoices |
$client->recurringInvoices |
Recurring invoices | recurring_invoices |
$client->auth |
User-token auth | - |
Each writable resource offers list(), autoPaging(), get(), create(),
update(), delete(). Quotes and invoices add lifecycle actions (issue,
send/cancel, setPaid, pdf); articles add variants. units and
documentTemplates are read-only - list(), autoPaging(), get().
Quotes::convert() is deprecated: POST /quotes/{id}/convert was retired on
2026-08-28 and now answers 410 on every call, so the method throws a local
GoneException (quote_conversion_moved) instead of making a request. A won
quote becomes an order, and the order is what gets invoiced - see AGENTS.md
for what that means for this client today.
Deprecations
recurring_invoice.document_ids - the attachment list carried as internal
INTEGER ids, the one place this API ever exposed them - is deprecated as of
the next minor release and removed in the next major release. Use
document_uuids, the same attachments addressed by uuid:
Nothing on the wire changes while both exist: the API keeps emitting and
accepting either key, and a request carrying both is applied from
document_uuids. Move anyway - an integer id belonging to another
organisation, or to nothing at all, is dropped in silence rather than refused,
so a wrong value cannot be told apart from a saved one.
Pagination
Lists return a Collection (data, total, limit, offset; iterable and
countable):
Or iterate everything lazily:
Error handling
Non-2xx responses throw a typed exception. Every one exposes
getStatusCode(), getErrorKey() (the stable slug) and getResponse().
| Exception | Status |
|---|---|
AuthenticationException |
401 |
PermissionException |
403 (incl. send_not_permitted / bank_not_permitted) |
NotFoundException |
404 |
ConflictException |
409 |
GoneException |
410 (a route retired for good, e.g. quote_conversion_moved) |
ValidationException |
400 / 422 |
RateLimitException |
429 |
ServerException |
5xx |
TransportException |
network failure (no response) |
All extend ApiException, so a single catch (ApiException $e) covers everything.
Custom HTTP client
Inject any PSR-18 client / PSR-17 factories (for a preconfigured Guzzle, retries, proxies, timeouts, test doubles ...):
Working models
Resource objects wrap the JSON payload: read documented fields as properties or array keys, and any field the API adds later stays reachable without a client upgrade.
Contributing / development
The API contract in openapi.yaml and the agent guide in AGENTS.md are part
of the release and are kept in sync with the API surface. The reasoning behind
them lives in docs/decisions/ as ADRs; a change that
affects more than one file, or that a consumer would notice, gets one.
License
MIT - see LICENSE.
All versions of api-client with dependencies
ext-json Version *
psr/http-client Version ^1.0
psr/http-factory Version ^1.0
psr/http-message Version ^1.1 || ^2.0
php-http/discovery Version ^1.19