Skip to content

feat: cleaning up webhooks#212

Open
pengying wants to merge 1 commit intomainfrom
02-19-feat_cleaning_up_webhooks
Open

feat: cleaning up webhooks#212
pengying wants to merge 1 commit intomainfrom
02-19-feat_cleaning_up_webhooks

Conversation

@pengying
Copy link
Contributor

@pengying pengying commented Feb 19, 2026

TL;DR

Updated webhook event type names to be more descriptive and consistent.

Changes defined in https://docs.google.com/document/d/1YdRboRlrwm0HKmRdyp-lbHZcfYUtJMF5NWk35vd_dZI/edit?tab=t.0

Copy link
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@pengying pengying marked this pull request as ready for review February 19, 2026 15:42
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 19, 2026

Greptile Summary

This PR renames webhook event types from flat identifiers (e.g., OUTGOING_PAYMENT, KYC_STATUS) to a descriptive dot-notation OBJECT.EVENT format (e.g., OUTGOING_PAYMENT.COMPLETED, CUSTOMER.KYC_APPROVED). It also standardizes the webhook envelope to use id/type/timestamp/data fields, replaces the transaction/invitation/etc. top-level fields with a uniform data field, moves the test webhook endpoint under /sandbox/, and introduces two new webhook types (InternalAccountStatusWebhook, CustomerKycWebhook) while deleting their predecessors.

Key issues found:

  • The retry policy table in mintlify/snippets/webhooks.mdx uses the pattern `ACCOUNT.*` but the actual enum prefix is INTERNAL_ACCOUNT.*, which will mislead developers implementing retry handling.
  • openapi/webhooks/customer-kyc.yaml describes EXPIRED and CANCELED as final states that fire a KYC webhook, but neither CUSTOMER.KYC_EXPIRED nor CUSTOMER.KYC_CANCELED exists in the CustomerKycWebhook.yaml enum or WebhookType.yaml.
  • CUSTOMER.KYC_SUBMITTED is present in the schema enum but the endpoint description explicitly states "The webhook will only trigger for final states" — KYC_SUBMITTED is not a final state, creating a contract contradiction.

The core rename and envelope restructuring is well-executed and internally consistent across most files. However, these three specification errors exist in the KYC webhook area and retry documentation — all of which would produce misleading documentation and incorrect consumer implementations.

Confidence Score: 3/5

  • Safe to merge after resolving the KYC webhook enum/description mismatches and the INTERNAL_ACCOUNT retry policy label.
  • The core rename and envelope restructuring is well-executed and internally consistent across most files. However, three concrete specification errors exist: (1) incorrect ACCOUNT.* prefix in retry docs instead of INTERNAL_ACCOUNT.*; (2) missing EXPIRED/CANCELED enum values that are documented as triggering states; (3) KYC_SUBMITTED enum value contradicts the "final states only" contract. All three would produce misleading documentation and incorrect consumer implementations if not resolved.
  • openapi/components/schemas/webhooks/CustomerKycWebhook.yaml, openapi/webhooks/customer-kyc.yaml, and mintlify/snippets/webhooks.mdx require attention.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    GW[Grid API] -->|fires| WH[Webhook Event]
    WH --> ENV["Envelope\nid / type / timestamp / data"]

    ENV --> OP["OUTGOING_PAYMENT.*\n.PENDING .PROCESSING\n.COMPLETED .FAILED .EXPIRED\n.REFUND_PENDING .REFUND_COMPLETED\n.REFUND_FAILED"]
    ENV --> IP["INCOMING_PAYMENT.*\n.PENDING .COMPLETED .FAILED"]
    ENV --> CK["CUSTOMER.*\n.KYC_APPROVED .KYC_REJECTED\n.KYC_SUBMITTED\n.KYC_MANUALLY_APPROVED\n.KYC_MANUALLY_REJECTED"]
    ENV --> IA["INTERNAL_ACCOUNT.*\n.BALANCE_UPDATED"]
    ENV --> BU["BULK_UPLOAD.*\n.COMPLETED .FAILED"]
    ENV --> IC["INVITATION.*\n.CLAIMED"]
    ENV --> TW["TEST"]

    OP -->|data| OT[OutgoingTransaction]
    IP -->|data| IT[IncomingTransaction]
    CK -->|data| IC2[IndividualCustomer]
    IA -->|data| IAS[InternalAccount + oldBalance]
    BU -->|data| BJ[BulkCustomerImportJob]
    IC -->|data| INV[UmaInvitation]
    TW -->|data| EMPTY["{}"]
Loading

Last reviewed commit: 6f28758

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

24 files reviewed, 7 comments

Edit Code Review Agent Settings | Greptile

@pengying pengying force-pushed the 02-19-feat_cleaning_up_webhooks branch from ac110b3 to 3a66bc6 Compare February 28, 2026 00:19
@github-actions
Copy link
Contributor

github-actions bot commented Feb 28, 2026

✱ Stainless preview builds

This PR will update the grid SDKs with the following commit messages.

kotlin

feat: cleaning up webhooks

openapi

feat(api): move test webhook to sandbox, restructure webhook payloads, update types to dot-notation

python

chore(api): move webhooks resource to sandbox namespace

typescript

feat(api): move sendTest method from webhooks to sandbox.webhooks

Edit this comment to update them. They will appear in their respective SDK's changelogs.

grid-openapi studio · code · diff

Your SDK build was successful, but this did not represent a regression.
generate ✅

grid-python studio · code · diff

Your SDK build had at least one "note" diagnostic, but this did not represent a regression.
generate ✅build ✅lint ✅test ✅

pip install https://pkg.stainless.com/s/grid-python/8e85e221b333920b2576746ffc694eebd2d42b73/grid-0.0.1-py3-none-any.whl
grid-kotlin studio · code · diff

Your SDK build had at least one "note" diagnostic, but this did not represent a regression.
generate ✅build ✅lint ✅test ✅

grid-typescript studio · code · diff

Your SDK build had at least one "note" diagnostic, but this did not represent a regression.
generate ✅build ✅lint ✅test ✅

npm install https://pkg.stainless.com/s/grid-typescript/3faec856eb78b5a4df3ca9b285a6b056f38b8749/dist.tar.gz

This comment is auto-generated by GitHub Actions and is automatically kept up to date as you push.
If you push custom code to the preview branch, re-run this workflow to update the comment.
Last updated: 2026-03-04 06:48:59 UTC

@pengying pengying force-pushed the 02-19-feat_cleaning_up_webhooks branch from 3a66bc6 to 3909f05 Compare February 28, 2026 00:22
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 28, 2026

Additional Comments (3)

openapi/components/schemas/invitations/UmaInvitation.yaml, line 1
Update description text from INVITATION_CLAIMED webhook to INVITATION.CLAIMED webhook to match the new dot-notation naming convention.

      platform once the INVITATION.CLAIMED webhook is received. If the inviter

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!


openapi/components/schemas/invitations/UmaInvitationCreateRequest.yaml, line 1
Update description text from INVITATION_CLAIMED webhook to INVITATION.CLAIMED webhook to match the new dot-notation naming convention.

      INVITATION.CLAIMED webhook is received. If the inviter

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!


openapi/paths/invitations/invitations_{invitationCode}_claim.yaml, line 1
Update description text from An INVITATION_CLAIMED webhook to An INVITATION.CLAIMED webhook to match the new dot-notation naming convention.

    3. An INVITATION.CLAIMED webhook is triggered to notify the platform that

@pengying pengying force-pushed the 02-19-feat_cleaning_up_webhooks branch 2 times, most recently from 12a7548 to 8c37e14 Compare February 28, 2026 20:08
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 28, 2026

Additional Comments (5)

openapi/components/schemas/invitations/UmaInvitation.yaml, line 59
Update webhook name reference from INVITATION_CLAIMED to INVITATION.CLAIMED

      platform once the INVITATION.CLAIMED webhook is received. If the inviter

mintlify/ramps/platform-tools/webhooks.mdx, line 73
Update tab to use new ACCOUNT.BALANCE_UPDATED webhook type and new envelope structure with id, type, timestamp, and data fields. The current example uses the old ACCOUNT_STATUS type and structure.


mintlify/ramps/platform-tools/webhooks.mdx, line 88
Update tab to use new CUSTOMER.KYC_* webhook types (e.g., CUSTOMER.KYC_APPROVED) and new envelope structure. The current example uses the old KYC_STATUS type and structure. See mintlify/snippets/kyc/kyc-webhooks.mdx for the updated structure.


mintlify/ramps/platform-tools/webhooks.mdx, line 248
Update to use new webhook type with dot-notation

if (type === "ACCOUNT.BALANCE_UPDATED") {

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!


mintlify/snippets/creating-customers/customers.mdx, line 170
Update webhook example to use new CUSTOMER.KYC_APPROVED type and envelope structure with id and data fields. The webhook structure has changed from having top-level fields to having a data object containing the customer resource.

@pengying pengying force-pushed the 02-19-feat_cleaning_up_webhooks branch from 8c37e14 to 0845a00 Compare March 2, 2026 20:53
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 2, 2026

Additional Comments (5)

mintlify/ramps/platform-tools/webhooks.mdx, line 248
Update webhook type references to new dot-notation format. The old types (OUTGOING_PAYMENT, ACCOUNT_STATUS, KYC_STATUS) should be updated to match the new naming convention:

  • OUTGOING_PAYMENTOUTGOING_PAYMENT.COMPLETED, OUTGOING_PAYMENT.FAILED, etc.
  • ACCOUNT_STATUSACCOUNT.BALANCE_UPDATED
  • KYC_STATUSCUSTOMER.KYC_APPROVED, CUSTOMER.KYC_REJECTED, etc.

Affects lines 17, 41, 50, 66, 75, 81, 178, 214, 248 with tab titles, JSON examples, and code comparisons.


mintlify/ramps/accounts/plaid.mdx, line 121
Update to new webhook type: ACCOUNT_STATUS should be ACCOUNT.BALANCE_UPDATED

  if (webhookPayload.type === 'ACCOUNT.BALANCE_UPDATED' && webhookPayload.account) {

mintlify/ramps/conversion-flows/fiat-crypto-conversion.mdx, line 151
Update to check for new webhook types. Since OUTGOING_PAYMENT is now split into status-specific types, this should check for type.startsWith("OUTGOING_PAYMENT.") or specific statuses like OUTGOING_PAYMENT.COMPLETED

  if (type.startsWith("OUTGOING_PAYMENT.") && transaction.status === "COMPLETED") {

mintlify/ramps/conversion-flows/fiat-crypto-conversion.mdx, line 200
Update to check for new webhook types. Use type.startsWith("OUTGOING_PAYMENT.") to handle all outgoing payment statuses

if (type.startsWith("OUTGOING_PAYMENT.") && transaction.status === "COMPLETED") {

mintlify/ramps/conversion-flows/self-custody-wallets.mdx, line 218
Update to check for new webhook types using prefix match

  if (type.startsWith("OUTGOING_PAYMENT.")) {

@pengying pengying force-pushed the 02-19-feat_cleaning_up_webhooks branch 3 times, most recently from 6c8bf4c to f585358 Compare March 3, 2026 00:55
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 3, 2026

Additional Comments (3)

openapi/components/schemas/webhooks/BaseWebhook.yaml, line 29
Discriminator removed — Stainless SDK webhook_unwrap may not resolve subtypes

The old BaseWebhook had a discriminator.mapping that explicitly mapped each type value to a specific schema (e.g., INCOMING_PAYMENT → IncomingPaymentWebhook). This was needed for the Stainless webhook_unwrap method that still declares discriminator: type in .stainless/stainless.yml.

With the new dot-notation types, multiple enum values map to the same schema — e.g., OUTGOING_PAYMENT.PENDING, OUTGOING_PAYMENT.COMPLETED, OUTGOING_PAYMENT.FAILED, and OUTGOING_PAYMENT.REFUNDED all correspond to OutgoingPaymentWebhook. Without a discriminator mapping, the Stainless generator and OpenAPI validators have no way to resolve a specific type value to the appropriate webhook schema.

Consider adding a discriminator back to BaseWebhook that maps every individual type value to its corresponding schema:

discriminator:
  propertyName: type
  mapping:
    OUTGOING_PAYMENT.PENDING: ./OutgoingPaymentWebhook.yaml
    OUTGOING_PAYMENT.COMPLETED: ./OutgoingPaymentWebhook.yaml
    OUTGOING_PAYMENT.FAILED: ./OutgoingPaymentWebhook.yaml
    OUTGOING_PAYMENT.REFUNDED: ./OutgoingPaymentWebhook.yaml
    INCOMING_PAYMENT.PENDING: ./IncomingPaymentWebhook.yaml
    INCOMING_PAYMENT.COMPLETED: ./IncomingPaymentWebhook.yaml
    INCOMING_PAYMENT.FAILED: ./IncomingPaymentWebhook.yaml
    CUSTOMER.KYC_APPROVED: ./CustomerKycWebhook.yaml
    CUSTOMER.KYC_REJECTED: ./CustomerKycWebhook.yaml
    CUSTOMER.KYC_SUBMITTED: ./CustomerKycWebhook.yaml
    CUSTOMER.KYC_MANUALLY_APPROVED: ./CustomerKycWebhook.yaml
    CUSTOMER.KYC_MANUALLY_REJECTED: ./CustomerKycWebhook.yaml
    ACCOUNT.BALANCE_UPDATED: ./AccountStatusWebhook.yaml
    INVITATION.CLAIMED: ./InvitationClaimedWebhook.yaml
    BULK_UPLOAD.COMPLETED: ./BulkUploadWebhook.yaml
    BULK_UPLOAD.FAILED: ./BulkUploadWebhook.yaml
    TEST: ./TestWebhookRequest.yaml

openapi/components/schemas/webhooks/CustomerKycWebhook.yaml, line 10
data locked to IndividualCustomer — business customers excluded

The data field references IndividualCustomer exclusively. If business customers can also undergo KYC (e.g., receiving CUSTOMER.KYC_APPROVED events), this schema would fail validation for their webhook payloads, and the SDK types would be incorrect.

If only individual customers trigger KYC webhooks this is intentional — but it is worth adding a comment to make that explicit. If business customers can also receive KYC webhooks, consider making data a union:

data:
  oneOf:
    - $ref: ../customers/IndividualCustomer.yaml
    - $ref: ../customers/BusinessCustomer.yaml

openapi/webhooks/outgoing-payment.yaml, line 45
Missing examples for OUTGOING_PAYMENT.PENDING and OUTGOING_PAYMENT.REFUNDED

The OutgoingPaymentWebhook schema exposes four event types (PENDING, COMPLETED, FAILED, REFUNDED), but this file only has examples for COMPLETED and FAILED. Consumers discovering the API through the docs will have no example payload to reference when handling PENDING approval flows or refund events. Consider adding examples for the two missing types.

@pengying pengying force-pushed the 02-19-feat_cleaning_up_webhooks branch from f585358 to d2d670f Compare March 3, 2026 02:37
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 3, 2026

Additional Comments (3)

openapi/components/schemas/webhooks/CustomerKycWebhook.yaml, line 5
data typed as IndividualCustomer only

CustomerKycWebhook.data is set to $ref: ../customers/IndividualCustomer.yaml, but the CUSTOMER.* event types (especially CUSTOMER.KYC_APPROVED/REJECTED) would logically apply to all customer types. If business customers can also undergo KYC/KYB verification and trigger these webhooks, the schema would be incorrect — consumers of this webhook for business customers would receive a payload that doesn't match the declared schema.

If business customers are never subject to these webhooks, a comment clarifying this constraint would prevent confusion. If they are, consider a oneOf/anyOf union:

data:
  oneOf:
    - $ref: ../customers/IndividualCustomer.yaml
    - $ref: ../customers/BusinessCustomer.yaml

openapi/components/schemas/webhooks/BaseWebhook.yaml, line 22
data description is inaccurate for IncomingPaymentWebhook

The data field description says "Contains the full resource as the corresponding GET endpoint would return it." However, IncomingPaymentWebhook.data is an allOf of IncomingTransaction plus requestedReceiverCustomerInfoFields — a field that is not part of the GET /transactions/{id} response. Developers relying on this description to understand the shape of data in an INCOMING_PAYMENT.PENDING event could be misled.

Consider adjusting the description to acknowledge that the data object may be augmented with webhook-specific fields:

data:
  type: object
  description: >-
    The primary resource object associated with this event. For most event types, 
    this mirrors the corresponding GET endpoint response, but may include 
    additional webhook-specific fields (e.g., requestedReceiverCustomerInfoFields 
    on INCOMING_PAYMENT.PENDING).

openapi/webhooks/outgoing-payment.yaml, line 88
Completed payment example has empty placeholder values

The completed outgoing payment example now contains paymentInstructions: [] and rateDetails: {}, replacing the previous version which showed realistic structured data. These empty values provide no guidance to developers on what to expect in a real webhook payload. The previous example with actual accountOrWalletInfo objects was more useful for integration.

Additionally, the 7 new OUTGOING_PAYMENT.* event types (PENDING, PROCESSING, SENT, REFUNDED, EXPIRED) have no examples at all. Similarly, INCOMING_PAYMENT.FAILED has no example in incoming-payment.yaml. Given the expanded set of event types, adding at least representative examples for the new states (like OUTGOING_PAYMENT.REFUNDED) would significantly improve developer experience.

@pengying pengying force-pushed the 02-19-feat_cleaning_up_webhooks branch from d2d670f to b2b3170 Compare March 3, 2026 20:16
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 3, 2026

Additional Comments (3)

docs/plans/2026-02-23-webhook-schema-design.md, line 339
Design doc type name doesn't match implementation

The design doc lists ACCOUNT_BALANCE.UPDATED but the actual implementation consistently uses ACCOUNT.BALANCE_UPDATED everywhere (in WebhookType.yaml, the bundled OpenAPI specs, and example payloads). This is ACCOUNT_BALANCE vs ACCOUNT as the object prefix.

The implementation's choice (ACCOUNT.BALANCE_UPDATED) makes more sense under the OBJECT.EVENT pattern, so the design doc likely has a typo. Please update the doc to match the code:

| `ACCOUNT.BALANCE_UPDATED` | Internal account balance changes |

docs/plans/2026-02-23-webhook-schema-design.md, line 332
Design doc KYC types don't match implementation

The design doc lists these KYC types with a KYC.* prefix and includes KYC.EXPIRED:

| `KYC.APPROVED` | ... |
| `KYC.REJECTED` | ... |
| `KYC.EXPIRED`  | KYC session expired |
| `KYC.MANUALLY_APPROVED` | ... |
| `KYC.MANUALLY_REJECTED` | ... |

But the implementation in WebhookType.yaml uses a CUSTOMER.KYC_* prefix and replaces KYC.EXPIRED with CUSTOMER.KYC_SUBMITTED:

  • CUSTOMER.KYC_APPROVED
  • CUSTOMER.KYC_REJECTED
  • CUSTOMER.KYC_SUBMITTED ← new, not in doc
  • CUSTOMER.KYC_MANUALLY_APPROVED
  • CUSTOMER.KYC_MANUALLY_REJECTED

Two things to clarify:

  1. Is CUSTOMER.KYC_EXPIRED intentionally dropped? If KYC sessions can still expire, the enum needs a CUSTOMER.KYC_EXPIRED value so consumers can route on it.
  2. The doc should be updated to use the CUSTOMER.KYC_* prefix and list CUSTOMER.KYC_SUBMITTED if that is the new intent.

openapi/components/schemas/webhooks/CustomerKycWebhook.yaml, line 9
KYC webhook data typed as IndividualCustomer only

CustomerKycWebhook.data is hard-referenced to IndividualCustomer. If business customers can also undergo KYC verification (and hence trigger CUSTOMER.KYC_* events), this schema would incorrectly describe the payload for those events — validators and SDK consumers would expect individual-only fields (fullName, birthDate, nationality, etc.) that a business customer wouldn't have.

If the KYC flow is intentionally restricted to individual customers only, please add a comment here to document that assumption. If business customer KYC events are (or will be) possible, the data field should be a oneOf/anyOf union:

data:
  oneOf:
    - $ref: ../customers/IndividualCustomer.yaml
    - $ref: ../customers/BusinessCustomer.yaml

@pengying pengying force-pushed the 02-19-feat_cleaning_up_webhooks branch from b2b3170 to acd1679 Compare March 4, 2026 02:16
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 4, 2026

Additional Comments (2)

openapi/components/schemas/webhooks/WebhookType.yaml, line 18
CUSTOMER.KYC_EXPIRED is missing from the enum. The design document included in this PR (docs/plans/2026-02-23-webhook-schema-design.md line 78) explicitly lists "KYC session expired" as a valid webhook type. If the backend emits this event, it will not match any recognized webhook type, breaking type-based routing in consumer applications.

Add this value to match the design specification:

  - CUSTOMER.KYC_APPROVED
  - CUSTOMER.KYC_REJECTED
  - CUSTOMER.KYC_SUBMITTED
  - CUSTOMER.KYC_MANUALLY_APPROVED
  - CUSTOMER.KYC_MANUALLY_REJECTED
  - CUSTOMER.KYC_EXPIRED

docs/plans/2026-02-23-webhook-schema-design.md, line 88
The webhook type names in this design document do not match the implementation. Update to align with actual enum values:

  1. KYC types (lines 76-80): Document says KYC.APPROVED, KYC.REJECTED, KYC.EXPIRED, etc., but the implementation uses CUSTOMER.KYC_APPROVED, CUSTOMER.KYC_REJECTED, CUSTOMER.KYC_EXPIRED, etc.

  2. Account type (line 88): Document says ACCOUNT_BALANCE.UPDATED, but the implementation uses ACCOUNT.BALANCE_UPDATED.

The design document is included in the repository for future reference. Correcting these names prevents confusion for future contributors who read this document to understand the webhook design.

keys: [ "type" ]

# ── beneficiaryType: beneficiary schemas ──
# # ── destinationType: transaction and quote destination schemas ──
Copy link
Contributor

Choose a reason for hiding this comment

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

qq should we remove these commented out sections, or were you keeping them here intentionally? just curious

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Generation is sometimes trial and error. Leaving these here until i feel totally comfortable with stainless.yml. Sometimes i go and uncomment some of these if something's not working as expected

description: The ID of the customer as associated in your platform
example: 019542f5-b3e7-1d02-0000-000000000001
enum:
- ACCOUNT.BALANCE_UPDATED
Copy link
Contributor

Choose a reason for hiding this comment

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

maybeee we should make this INTERNAL_ACCOUNT.BALANCE_UPDATED? feels like external account webhooks are coming soon

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good call out, updated

…ation types

- Adopt OBJECT.EVENT dot-notation for all webhook types (e.g., OUTGOING_PAYMENT.COMPLETED)
- Wrap all webhook data under a unified `data` key (Stripe-style full resource embed)
- Rename webhook files to match resource-event pattern
- Move test webhook endpoint to /sandbox/webhooks/test
- Update documentation and examples to match new schema
@pengying pengying force-pushed the 02-19-feat_cleaning_up_webhooks branch from acd1679 to 6f28758 Compare March 4, 2026 06:42
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 4, 2026

Additional Comments (3)

mintlify/snippets/webhooks.mdx, line 205
The retry policy table uses ACCOUNT.* as the webhook type pattern, but the actual enum value introduced in this PR is INTERNAL_ACCOUNT.BALANCE_UPDATED (prefix INTERNAL_ACCOUNT.*). A developer reading this table would set up a wrong type-match and miss retries for this webhook category.

| `INTERNAL_ACCOUNT.*` | Retry with exponential backoff up to 7 days with maximum interval of 30 mins | No retry on 409 (duplicate webhooks) |

openapi/webhooks/customer-kyc.yaml, line 44
Line 34 explicitly states the webhook fires for EXPIRED and CANCELED final states, yet neither CUSTOMER.KYC_EXPIRED nor CUSTOMER.KYC_CANCELED appears in CustomerKycWebhook.yaml's type enum (which only has CUSTOMER.KYC_APPROVED, CUSTOMER.KYC_REJECTED, CUSTOMER.KYC_SUBMITTED, CUSTOMER.KYC_MANUALLY_APPROVED, CUSTOMER.KYC_MANUALLY_REJECTED). API consumers who implement handling for these states per the docs will never receive matching events, and OpenAPI tooling will reject them as unknown values.

Either add the missing enum values to openapi/components/schemas/webhooks/CustomerKycWebhook.yaml and openapi/components/schemas/webhooks/WebhookType.yaml, or remove the references to EXPIRED and CANCELED from this description.


openapi/components/schemas/webhooks/CustomerKycWebhook.yaml, line 14
openapi/webhooks/customer-kyc.yaml line 34 explicitly states: "The webhook will only trigger for final states." KYC_SUBMITTED (i.e., when a KYC session is first submitted) is an intermediate/in-progress state, not a final state. Including it in the type enum here — and in WebhookType.yaml — contradicts the documented contract and may cause consumers to prematurely act on what they expect is a final decision.

If this event type is intentionally supported, the description in customer-kyc.yaml must be updated to say the webhook also fires for submission events. If it is not yet supported, remove it from both enums to avoid confusion.

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.

3 participants