PrestaShop 9.2 Admin API Changes: Carrier and Response Contracts

46 Views

An API client can break even when the URL it calls has not changed. A required field may be described more accurately, a missing entity may now produce an explicit failure, or a query result may pass through a different internal mapping path. Those are contract questions that deserve targeted tests.

PrestaShop 9.2 RC1 includes carrier-domain and API work, plus a change for list-returning CQRS queries. This article examines those concrete changes and their integration implications. It assumes familiarity with the Admin API and does not repeat authentication or API Platform fundamentals.

The review is current to September 26, 2026. RC1 remains an evaluation target; the examples below describe contract-testing methods, not verified responses from a running store in this project.

If an API response includes custom fields, include the Extra Properties module integration workflow in the contract review rather than assuming every registered field should be exposed.

Carrier support spans the core and resource module

The carrier work in core is linked to resource work in ps_apiresources. The merged core PR identifies fixes needed to make the carrier resources operate correctly, including scalar query arguments, modern shop context and a missing-product check. Carrier domain and API change #42022.

For client developers, the immediate implication is to record both versions. “Core 9.2” does not fully describe the resource inventory installed on a particular shop. Before adopting an operation, inspect the generated documentation in that installation and verify its availability with an authorized sandbox request.

Do not copy a proposed route from an issue discussion and assume it shipped. A core change can support a resource that is packaged separately, and a review comment can describe an earlier iteration. Use the installed schema and matching source revision together.

Build the smallest useful carrier fixture: a known carrier, a product associated with the relevant shop and a deliberately nonexistent product identifier. Keep shipping rules simple initially so a domain validation failure is not confused with an eligibility rule.

Generated request schemas are part of the contract

The same carrier PR addresses request-body documentation derived from commands: omitted properties, requiredness and resource-provided schema context. It also adds handling for operation defaults before mapping and validation. Schema and default-value details.

That is important for generated clients. A stale schema can encourage a client to omit information the operation needs or represent nested values incorrectly. Regenerating a client without inspecting the diff can then introduce changes far beyond the operation being adopted.

Capture the baseline schema and the candidate schema from their respective installations. Review required fields, nullability, array item shapes and defaults. Confirm which differences affect operations your client actually calls.

A documented default is not a reason to send null indiscriminately. Omitted, null and explicit values can have different meanings. Test each state that your application may produce and record the resulting behavior.

For a write operation, compare the saved entity with the request, not only the HTTP result. A request can be accepted while a default produces a result different from the client’s business expectation.

Missing entities and shop scope need negative cases

A meaningful contract test includes an identifier that cannot exist in the fixture. The carrier work makes setting references on an unknown product fail explicitly rather than silently doing nothing. Missing-product behavior.

Your client should treat that as a failed business operation. Logging a successful synchronization merely because a transport request completed would hide the distinction.

Also test a real entity in an inappropriate shop context. A valid global identifier is not proof that an operation is valid in every shop. Use the installed operation’s documented scope mechanism and verify the resulting association or value in the intended shop.

Avoid silently substituting the default shop when context is missing. If your application requires a single-shop operation, validate that requirement before dispatch. A client-side precondition can prevent a vague server failure and make the intended scope clearer in logs.

Do not equate an empty eligibility result with an error. A valid request may correctly find no eligible carriers. Keep that result distinct from denied access, an invalid product or a server exception.

List-query mapping does not mean every response has a new wrapper

A separate 9.2 change wraps plain list results from non-collection CQRS operations under an internal _queryResult mapping key. Associative results retain their existing mapping behavior. The PR explains that the key allows a list result to be assigned to a resource property. List-result mapping #42011.

The crucial distinction is between the internal mapping input and the public response representation. Do not tell every API client to expect a top-level _queryResult property. The resource mapping and serialization determine the exposed shape.

For an extension implementing a suitable resource, verify a populated list and an empty list. The empty result is important because code often treats it as missing data or an unexpected type. The client should receive the documented representation for both.

If you maintain contract snapshots, compare parsed structure rather than irrelevant formatting or property order. A useful assertion checks the expected field type and values. A raw text comparison can fail on harmless serialization changes while overlooking a semantic mismatch elsewhere.

This change is a focused mapping improvement. It is not evidence that all collection operations or all existing clients require a rewrite.

Extra Properties exposure adds a data-contract dimension

When an integration adopts a newly registered property, treat that property as part of the business contract. Define its owner, type, empty-value meaning and shop or language scope before letting another system write it.

Do not infer the external payload from a field’s administrative label. Inspect the installed resource schema and a verified example response. Preserve the module namespace and the exact supported representation in your client mapping.

A field can be available in an administrative form while an integration has not been configured or authorized to consume it. Conversely, an exposed value may inherit the parent entity’s permissions rather than having a separate field-level policy. Verify that behavior in the current feature documentation and installation.

For a new property, add round-trip cases: write a valid value, read it back, clear it if supported, reject an invalid value and verify a second shop remains unchanged. Keep those cases separate from ordinary product fields so failures identify the new extension surface.

If you do not use Extra Properties, do not expand your client’s write payload merely because the candidate can expose them. Adopt only the fields your business contract needs.

Build a small contract-diff workflow

The following Python helper compares the path and method inventory of two locally saved OpenAPI JSON files. It does not fetch a shop, authenticate or validate operation behavior:

import json
from pathlib import Path

METHODS = {"get", "post", "put", "patch", "delete", "head", "options"}

def operations(filename):
    document = json.loads(Path(filename).read_text(encoding="utf-8"))
    return {
        (method.upper(), path)
        for path, item in document.get("paths", {}).items()
        for method in item
        if method.lower() in METHODS
    }

before = operations("baseline-openapi.json")
after = operations("candidate-openapi.json")
print("Added:", sorted(after - before))
print("Removed:", sorted(before - after))

Use filenames for the schema exports you actually saved. An unchanged inventory still requires a schema comparison for the operations you use. Request parameters, body schemas, response schemas and permissions can change without adding or removing a path.

After the static diff, run a small suite against synthetic records: authorized read, valid write, invalid input, missing entity, empty result and relevant shop scope. Inspect the persistent result of each write.

Do not capture tokens in fixtures or commit raw production responses. Redact identifiers where appropriate and use synthetic customer data so contract evidence is safe to share with maintainers.

Distinguish missing support from incompatible support

If an operation is absent from the candidate schema, record it as unavailable in that version pair. Do not send a guessed request and interpret a routing failure as evidence that the new domain implementation is broken.

If the operation exists but rejects a documented payload, retain the schema excerpt, sanitized request and response. That is a different class of compatibility issue and can be reported with a precise contract mismatch.

For generated clients, keep the generated code revision beside the schema export. A developer may otherwise test a current server with an old client and attribute the client’s serialization choice to the server. Reproduce with a minimal supported request before changing either side.

These distinctions make an API migration report actionable: unavailable operation, schema mismatch, serialization defect and business validation failure each point to a different owner.

Release the client against a named version pair

A compatibility statement should identify the core and resource-module versions, the adopted operations and any limitations. If a new operation is absent, disable the dependent feature explicitly rather than failing later during an unrelated workflow.

When an operation returns an uncertain outcome after a timeout, reconcile before repeating a consequential write. The 9.2 schema improvements do not remove distributed-system failure modes.

The main developer task is therefore narrow: inspect the actual resource contract, test the carrier and mapping changes you depend on, and preserve evidence that the client’s assumptions still hold. That is more reliable than treating the new release as an invitation to regenerate everything blindly.

For the underlying platform context, see our PrestaShop 9 Admin API guide and apply the version-specific checks above to the installation you are evaluating.

When selecting an extension, browse PrestaSuite’s PrestaShop 9 modules and check the documented version support and integration requirements against your own test results.