lambda-twelve / one-record
A framework-agnostic PHP server (PSR-15) and client (PSR-18) implementation for the IATA ONE Record API.
Requires
- php: >=8.3
- ext-json: *
- ext-openssl: *
- psr/clock: ^1.0
- psr/event-dispatcher: ^1.0
- psr/http-factory: ^1.1
- psr/http-message: ^1.1 || ^2.0
- psr/http-server-handler: ^1.0
- psr/log: ^2.0 || ^3.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.75
- guzzlehttp/guzzle: ^7.9
- nyholm/psr7: ^1.8.2
- nyholm/psr7-server: ^1.1
- phpstan/phpstan: ^2.1
- phpstan/phpstan-phpunit: ^2.0
- phpstan/phpstan-strict-rules: ^2.0
- phpunit/phpunit: ^11.5
- psr/http-client: ^1.0
- psr/simple-cache: ^2.0 || ^3.0
Suggests
- phpunit/phpunit: To run the store contract tests in Testing\Contract against your own SPI implementations
- psr/http-client: To use the ONE Record client (talking to partners' servers) and the JWKS key resolver: any PSR-18 HTTP client
- psr/simple-cache: To cache partner tokens, server information and JWKS documents: any PSR-16 cache
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-05 08:52:01 UTC
README
A framework-agnostic PHP implementation of IATA ONE Record: the server side (a data holder publishing logistics objects to partners) and the client side (talking to other parties' ONE Record servers), as one Composer package.
Status: in beta on Packagist: API 2.2.0 and 2.3.0 served and consumed, compliance and NE:ONE interoperability green, every release signed and tagged (the badges above show the current one). Betas follow the review rounds of the Laravel and Drupal integrations and of independent adversarial reviews; public API changes are still allowed between betas and recorded in the changelog. The roadmap has the detail.
What it supports
| Specification | Versions |
|---|---|
| ONE Record API | 2.2.0 and 2.3.0, negotiated per request (Accept: application/ld+json; version=…) and per partner in the client |
| ONE Record cargo ontology (data model) | 3.2 and 3.3 |
| ONE Record code lists | 1.1.0 |
Every endpoint of both API editions, the action-request lifecycle, notification fan-out, access delegations, verification requests and the optional 2.3 bulk events; a client for all of it; RS256 JWT verification and a client-credentials token endpoint. Proven by 460+ PHPUnit tests, a newman compliance collection run per API version, and an interoperability suite against NE:ONE comparing both servers' answers as RDF.
Requirements
PHP 8.3 or newer with ext-json and ext-openssl. Runtime dependencies are
PSR interfaces only; you bring the implementations your application already
uses (PSR-7/17 messages, PSR-18 client, PSR-14 dispatcher, PSR-20 clock,
PSR-3 logger, PSR-16 cache).
Installation
composer require lambda-twelve/one-record:^1.0@beta
The @beta flag lets Composer pick a pre-release without lowering your
project's minimum stability for everything else. Once 1.0.0 is out,
composer require lambda-twelve/one-record is enough.
Server in five lines
$server = new InMemoryServer(new ServerConfig('https://1r.example.com', $holderIri), $authenticator, new SystemClock(), $dispatcher, $psr17, $psr17); $server->policy->addInternal($holderIri); (new DataHolder($server->services))->create($piece); // publish your data in PHP $server->policy->allow($partnerIri, $piece->iri, [Permission::GetLogisticsObject]); $response = $server->handler->handle($request); // the PSR-15 handler you mount
InMemoryServer wires in-memory implementations of every SPI interface. A
host replaces them one at a time with its own (a database, a queue) and keeps
the same contract tests green; Testing\Contract ships them.
Client in three lines
$client = new OneRecordClient($psr18, $psr17, $psr17, $tokens, 'https://1r.partner.example'); $piece = $client->getLogisticsObject($iri); // negotiates the API version first $request = $client->requestChange((new ChangeBuilder())->diff($piece->object, $wanted, $piece->revision));
What a host implements
Eight small interfaces in Server\Spi: object, event, action-request,
subscription and access-delegation stores, a notification outbox, an
authenticator and an access policy, plus an optional unit of work for
transactions. Everything else, including every endpoint, the lifecycle rules
and the JSON-LD, is the SDK's. The
SDK boundary page
draws the line and PHPStan enforces it. Wrappers for Laravel
(lambda-twelve/one-record-laravel) and Drupal are built on exactly this.
Documentation
Getting started for the server and the client, the SPI guide, the JSON-LD subset, action requests, notifications, spec coverage per endpoint, the NE:ONE interoperability results and every open specification question: https://lambda-twelve.github.io/one-record/.
Maintained by Lambda Twelve
Developed and maintained by Lambda Twelve, an independent software engineering company based in the EU. We build and operate logistics and air-cargo systems, and we publish the infrastructure they need as open source: this SDK, its Laravel and Drupal integrations, and the specification questions and interoperability findings they produce, which we share upstream with IATA.
Issues and pull requests are welcome; see CONTRIBUTING.md. Security vulnerabilities should be reported privately as described in SECURITY.md.
Licence
Apache-2.0. The ONE Record specification and ontologies are IATA's, licensed
under the MIT License; see NOTICE. NE:ONE, used only as a test oracle, is the
Open Logistics Foundation's (OLFL-1.3) and is not part of this package.