Skip to content

Send numeric service code in product.id for Booking API#62

Merged
crakter merged 2 commits into
masterfrom
claude/brave-bardeen-S4zZM
Jun 1, 2026
Merged

Send numeric service code in product.id for Booking API#62
crakter merged 2 commits into
masterfrom
claude/brave-bardeen-S4zZM

Conversation

@crakter
Copy link
Copy Markdown
Owner

@crakter crakter commented Jun 1, 2026

Summary

Bring's Booking API expects the numeric service code in product.id (e.g. "5000" for BUSINESS_PARCEL, "9000" for the return variant) — the same codes the v3 SDK used. The v4 SDK was sending the string enum value ("BUSINESS_PARCEL"), which Bring's gateway looks up in the international catalog and rejects Norway→Norway routes with:

  • BOOK-INPUT-025 "The product is not available between the given countries"
  • BOOK_VALIDATION-014 "Customs declarations are required for exporting this product from Norway"

— even though both parties are "NO". This was an unnoticed v3→v4 regression; the existing BookingApiTest only checked the incorrect shape against a mock client.

The Shipping Guide path is unchanged: PriceRequest::toArray keeps using the string Product enum value, which is the correct v2 Shipping Guide convention.

Change

  • Product::bookingProductId(): string — returns the numeric service code as a string for products with a known mapping, falls back to the enum value otherwise (so newer products with no v3 numeric counterpart still work via the string Bring accepts in some contexts).
  • BookingProduct::toArray() calls bookingProductId() instead of $id->value.
  • BookingApiTest switched to BUSINESS_PARCEL and pins the serialized id to "5000".

Mapped codes (from the v3 numeric catalog Bring still accepts in v4 Booking):

Code Product
3570 MAILBOX_PARCEL_TRACKED
3584 MAILBOX_PARCEL
4850 EXPRESS_NORDIC_0900
5000 BUSINESS_PARCEL
5100 BUSINESS_PARCEL_BULK
5300 CARGO_GROUPAGE
5800 PICKUP_PARCEL
5802 PICKUP_PARCEL_BULK
9000 RETURN_BUSINESS_PARCEL
9100 RETURN_BUSINESS_PALLET
9300 RETURN_PICKUP_PARCEL

Verified the wire shape locally:

"product": { "id": "5000", "customerNumber": "PARCELS_NORWAY-..." }

Test plan

  • vendor/bin/phpunit — 198 tests, all green
  • vendor/bin/phpstan analyse — no errors
  • Direct JSON dump confirms product.id is now "5000" for BUSINESS_PARCEL

Generated by Claude Code

Bring's Booking API expects the numeric service code in
product.id (e.g. "5000" for BUSINESS_PARCEL, "9000" for
BUSINESS_PARCEL_RETURN) — the same codes the v3 SDK used. The
v4 SDK was sending the string enum value (BUSINESS_PARCEL),
which Bring's gateway looks up in the international catalog and
rejects Norway→Norway routes with BOOK-INPUT-025 ("product not
available between the given countries") plus BOOK_VALIDATION-014
("customs declarations required for exporting from Norway"),
even though both parties are NO. This was an unnoticed v3→v4
regression — the existing BookingApiTest only checked the
incorrect shape against a mock client.

The Shipping Guide path is unchanged: PriceRequest::toArray
keeps using the string Product enum value, which is correct for
the v2 Shipping Guide endpoint.

Implementation notes:
- New Product::bookingProductId(): returns the numeric code as
  string for products with a known mapping, falls back to the
  enum value otherwise. Keeps unknown products at least as
  functional as today (Bring accepts strings for some newer
  products).
- BookingProduct::toArray() now calls bookingProductId() instead
  of ->value.
- BookingApiTest switched to BUSINESS_PARCEL and pins the
  serialized id to "5000".

Mapped service codes (from the v3 numeric catalog Bring still
accepts in v4 Booking): PICKUP_PARCEL 5800, PICKUP_PARCEL_BULK
5802, BUSINESS_PARCEL 5000, BUSINESS_PARCEL_BULK 5100,
EXPRESS_NORDIC_0900 4850, MAILBOX_PARCEL 3584,
MAILBOX_PARCEL_TRACKED 3570, CARGO_GROUPAGE 5300,
RETURN_PICKUP_PARCEL 9300, RETURN_BUSINESS_PARCEL 9000,
RETURN_BUSINESS_PALLET 9100.
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the Booking API integration to send numeric service codes instead of string enum values for product IDs, resolving potential validation errors for domestic Norway shipments. Feedback points out that several standard products and their return variants (such as HOME_DELIVERY_PARCEL, BUSINESS_PALLET, and RETURN_HOME_DELIVERY_PARCEL) are missing from the numeric mapping, which could still trigger validation errors if left unmapped.

Comment thread src/v4/Enum/Product.php
Comment on lines +78 to +91
$numeric = match ($this) {
self::PICKUP_PARCEL => 5800,
self::PICKUP_PARCEL_BULK => 5802,
self::BUSINESS_PARCEL => 5000,
self::BUSINESS_PARCEL_BULK => 5100,
self::EXPRESS_NORDIC_0900 => 4850,
self::MAILBOX_PARCEL => 3584,
self::MAILBOX_PARCEL_TRACKED => 3570,
self::CARGO_GROUPAGE => 5300,
self::RETURN_PICKUP_PARCEL => 9300,
self::RETURN_BUSINESS_PARCEL => 9000,
self::RETURN_BUSINESS_PALLET => 9100,
default => null,
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Several common products and their return variants appear to be missing from the numeric mapping. Specifically, HOME_DELIVERY_PARCEL (5600), BUSINESS_PALLET (5200), and RETURN_HOME_DELIVERY_PARCEL (9600) are standard Bring products. Without these mappings, booking requests for these products will fall back to their string enum values, which will trigger the same BOOK-INPUT-025 / BOOK_VALIDATION-014 validation errors for domestic Norway shipments.

Adding these mappings ensures complete coverage for all standard products supported by the Booking API.

        $numeric = match ($this) {
            self::PICKUP_PARCEL => 5800,
            self::PICKUP_PARCEL_BULK => 5802,
            self::HOME_DELIVERY_PARCEL => 5600,
            self::BUSINESS_PARCEL => 5000,
            self::BUSINESS_PARCEL_BULK => 5100,
            self::BUSINESS_PALLET => 5200,
            self::EXPRESS_NORDIC_0900 => 4850,
            self::MAILBOX_PARCEL => 3584,
            self::MAILBOX_PARCEL_TRACKED => 3570,
            self::CARGO_GROUPAGE => 5300,
            self::RETURN_PICKUP_PARCEL => 9300,
            self::RETURN_BUSINESS_PARCEL => 9000,
            self::RETURN_BUSINESS_PALLET => 9100,
            self::RETURN_HOME_DELIVERY_PARCEL => 9600,
            default => null,
        };

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Holding off on these specific mappings. Cross-referencing against the v3 SDK's Crakter\BringApi\DefaultData\Products catalog (which is the source for the codes I did add), I can't confirm any of the three:

  • 9600 in v3 is RETUREKSPRESS (return-express, i.e. the return variant of EXPRESS_NORDIC_0900) — not RETURN_HOME_DELIVERY_PARCEL. Mapping it as the home-delivery return would silently book the wrong product.
  • 5200 doesn't appear in the v3 numeric catalog at all.
  • 5600 also doesn't appear there. (And a separate developer.bring.com lookup showed 5600 candidate as a "DISTRIBUTION" code — different again.)

A wrong numeric code silently books the wrong product; the current string fallback at worst surfaces a 4xx, which is the safer failure mode. Documented the gap on the method so the next person hitting BOOK-INPUT-025 on an unmapped product knows to look up the code in Mybring rather than guess — see c2dc9bf.

If you have authoritative codes for these from Bring's product catalog, happy to add them.


Generated by Claude Code

@crakter crakter merged commit 913f1d2 into master Jun 1, 2026
18 checks passed
@crakter crakter deleted the claude/brave-bardeen-S4zZM branch June 1, 2026 20:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants