Skip to content

docs/Webhooks.md is out of sync with the code (payload shape, event names, missing helper) #17

@sandervanhooft

Description

@sandervanhooft

While writing the official TypeScript SDK against the OpenAPI spec, I cross-checked docs/Webhooks.md against the actual PHP code and found four mismatches. The DTOs in src/API/ are correct against the spec; the docs describe a shape that no class in this repo models.

1. Webhook payload shape

docs/Webhooks.md describes the payload as:

{ id, type, data, createdAt }

The actual DTO in src/API/Resources/WebhookEvent.php is:

{ id, resource, eventName, entityType, entityId, object, links }

This also matches the OpenAPI spec's WebhookEvent schema and the fixture in tests/Endpoints/WebhookEventEndpointTest.php. The docs' field names (type, data, createdAt) don't exist anywhere in the codebase.

2. Event name list

The docs list event names like checkout.paid, checkout.failed, subscription.created, subscription.renewed, subscription.ended, refund.created, chargeback.created, chargeback.won, chargeback.lost. None of these are constants in src/API/Types/WebhookEvent.php.

The actual constants are: order.paid, order.canceled, order.chargeback_received, order.chargeback_reversed, refund.completed, refund.failed, refund.canceled, subscription.started, subscription.canceled_immediately, subscription.canceled_with_grace_period, subscription.cancellation_grace_period_completed, checkout.expired.

Only order.paid, refund.completed, and checkout.expired overlap.

3. Webhook::parse() doesn't exist

Both the standalone PHP example and the Laravel example reference:

use Vatly\API\Webhook;
$event = Webhook::parse($payload, $signature, $secret);

No Vatly\API\Webhook class exists in src/. The only verifier is src/API/Webhooks/WebhookSignatureValidator.php, which exposes verify($payload, $signature) / isValid(...) / calculateSignature(...). Either Webhook::parse() needs to be added, or the examples should be rewritten against the existing validator.

4. Header name — can you confirm?

The docs read $_SERVER['HTTP_VATLY_SIGNATURE'] and $request->header('Vatly-Signature'), both of which correspond to the HTTP header Vatly-Signature (no X- prefix). I've separately seen X-Vatly-Signature cited as the canonical name. The PHP code itself doesn't read the header (the validator takes the signature as a string param), so the docs are currently the only source of truth — and there's no test exercising a real delivery.

Could you confirm which one Vatly actually sends on the wire? Whichever it is, the docs should match.

Suggested fix

Happy to PR a rewrite of docs/Webhooks.md against the real DTOs and an inferred Webhook::parse() convenience (or just route the examples through WebhookSignatureValidator + manual json_decode). Let me know which direction you'd prefer.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions