Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Core Laravel Package

apimatic/core

Core library for APIMatic-generated PHP SDKs. It supplies shared request construction, query/header/form/body parameter handling, and common utilities so generated clients stay consistent. Supports PHP 7.2 through 8.4; install with composer require apimatic/core.

View on GitHub
Deep Wiki
Context7

Getting Started

This is not a package you normally write code against. apimatic/core is the runtime substrate that APIMatic's code generator emits into your SDKs. In practice you meet it as a transitive dependency of a generated client (e.g. composer show apimatic/core reveals it pulled in by a *-sdk package). Treat direct composer require "apimatic/core" as the exception, not the rule — if a generated SDK pins a version range, adding your own constraint is how you get composer conflicts.

Minimal steps:

# Usually this, not the core lib directly
composer require vendor/some-api-sdk

# Confirm the runtime is present and which version the SDK pinned
composer show apimatic/core

There is no service provider, no config/apimatic.php to publish, no facade. Everything is constructor injection and plain objects. First thing to read is src/Request/RequestBuilder.php and src/Response/ResponseHandler.php — those two files explain 80% of the call path. Then src/Logger/ApiLogger.php and src/TestCase/CoreTestCase.php.

First use case: wrap the generated SDK in a Laravel service class, bind it as a singleton with credentials from config(), and route the SDK's logging through your application log channel:

// app/Providers/ApiServiceProvider.php
$this->app->singleton(SomeApiClient::class, fn () => new SomeApiClient(
    config('services.someapi.token')
));

Then, once something breaks in staging, the second use case is turning on request/response logging (see below) — that's the fastest path from "SDK returns null" to "here's the 400 body".

Implementation Patterns

Isolate the SDK behind your own boundary. Generated clients expose hundreds of methods with generated DTOs. Don't let those DTOs leak into controllers or Blade views. Wrap in a repository-ish class, map to your own arrays/models, and let the SDK be swappable:

final class PaymentGateway
{
    public function __construct(private SomeApiClient $client) {}

    public function charge(Order $order): array
    {
        $resp = $this->client->getPaymentsApi()->createPayment($order->total_cents);
        return ['id' => $resp->getId(), 'status' => $resp->getStatus()];
    }
}

Inject cross-cutting concerns as additional params. AdditionalHeaderParams, AdditionalQueryParams, and AdditionalFormParams exist precisely for the things your app knows and the API definition doesn't — correlation IDs, tenant IDs, feature flags. Build them from the current request context rather than hardcoding:

new AdditionalHeaderParams([
    'X-Request-Id' => (string) Str::uuid(),
    'X-Tenant'     => tenant()->id,
]);

Logging is opt-in and defaults to silence. NullApiLogger is the default; nothing is recorded until you pass a LoggingConfiguration. Bridge it to Laravel's logger with a small custom ApiLogger implementation that calls Log::channel('api'), then supply RequestConfiguration / ResponseConfiguration with sensitive headers excluded (see LoggerConstants::NON_SENSITIVE_HEADERS — note the name; anything not in that allowlist must be treated as secret). Long-running queue workers should log at debug level only, or you'll flood the channel.

Error handling via ResponseError + ErrorType gives you typed exceptions per HTTP status range. Catch the SDK's specific exception classes, not \Throwable, and translate them into your app's domain exceptions at the boundary. Since 0.3.7 the library throws the actual exceptions rather than wrappers, so instanceof checks now behave the way you'd expect — but that also means any code written against the older wrapper types needs review.

Testing with CoreTestCase is where this package earns its keep in a Laravel codebase. The matchers let you assert on the raw wire exchange without standing up a real server:

$testCase = new CoreTestCase();
$testCase->assertResponse(
    $response,
    new StatusCodeMatcher(200),
    new HeadersMatcher(['Content-Type' => 'application/json']),
    new KeysAndValuesBodyMatcher(['id' => 'abc', 'status' => 'ok'])
);

Use KeysBodyMatcher when you only care about schema shape, RawBodyMatcher only when byte-exact output matters (signing, hashing). For integration tests inside Laravel, prefer Http::fake() against the SDK's underlying client where possible, and reserve CoreTestCase for contract tests against recorded fixtures.

Retries and queues: the core lib has no retry policy. Put retries in your job layer with Laravel's retry()/backoff(), and only retry idempotent operations — the SDK will happily re-send a POST.

Gotchas and Tips

  • 0.x semver means minor bumps can break you. The release history is full of behaviour fixes (0.3.7 exception unwrapping, 0.3.5 simple-date deserialization, 0.3.4 negative RFC3339 offsets, 0.3.2 unquoted multipart booleans). Pin with ^0.3.x at minimum and read release notes before bumping — a date-parsing fix can silently change your persisted timestamps.
  • No Laravel integration ships with it. You own the singleton binding, the config keys, and the logger adapter. If you skip the binding, every resolution constructs a fresh client with a fresh logger and you'll lose connection reuse.
  • ConsoleLogger writes to stdout. In an artisan command that's fine; in a web request it corrupts JSON responses and in Octane it leaks into the worker output. Always swap in a Log-backed implementation.
  • Redaction is a denylist problem. Verify exactly what your logging config includes before enabling it in production — auth headers, Authorization, cookies, and request bodies containing PII are the usual leaks. Test by logging a request with a dummy bearer token and grepping the output.
  • Deserialization is silent and lossy in places. Unknown fields are dropped and type mismatches may coerce rather than throw. If a field arrives null unexpectedly, dump the Context object (available on ResponseHandler) — it holds the raw request, raw response, and intermediate details, which is far quicker than adding dd() around the SDK.
  • Multipart with booleans was broken pre-0.3.2 (booleans sent quoted, so servers read the string "false" as truthy). If an older generated SDK drags in an older core, this is a real production bug.
  • Don't judge it by the star count. 7 stars and 0 Packagist dependents is misleading: the actual consumers are generated SDKs published under thousands of vendor namespaces, which composer doesn't surface as dependents. Look at the Sonar coverage badge and the release cadence instead — both are healthy.
  • Extension points are subclassing, not configuration: custom ApiLogger, custom body matchers extending the provided ones, and custom type handlers alongside DeserializableType for enums/dates. Prefer wrapping over subclassing where you can, since generated code is regenerated and your subclasses must survive that.
  • PHP 7.2 support is still advertised, so don't assume the internals use typed properties or constructor promotion — reading the source will look older than the rest of your Laravel 11 codebase.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log