Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
8db5673
fix(openapi): propagate webhook responses from OpenAPI to IR
devin-ai-integration[bot] Dec 9, 2025
777127d
fix: add responses field to convertWebhookGroup.ts
devin-ai-integration[bot] Dec 9, 2025
bfd1745
fix: update v3-importer-tests webhook snapshot
devin-ai-integration[bot] Dec 9, 2025
b8a428f
fix: update ir-generator-tests webhook snapshots
devin-ai-integration[bot] Dec 9, 2025
a48fb8c
fix: update ete-tests webhook snapshot
devin-ai-integration[bot] Dec 10, 2025
7783183
fix(openapi): add IR migration and changelog for webhook responses
devin-ai-integration[bot] Dec 10, 2025
c3bce71
Merge origin/main into devin/1765317066-webhook-responses-fix
devin-ai-integration[bot] Dec 10, 2025
178b773
fix(openapi): correct changelog version to 3.7.0 for feat type
devin-ai-integration[bot] Dec 10, 2025
0da9393
refactor(openapi): use HttpResponse type instead of WebhookResponse
devin-ai-integration[bot] Dec 10, 2025
3a6d804
Merge origin/main into devin/1765317066-webhook-responses-fix
devin-ai-integration[bot] Dec 10, 2025
d7d9849
Merge origin/main and move v63-to-v62 migration to v62-to-v61
devin-ai-integration[bot] Dec 10, 2025
764e4c7
chore: bump webhook responses changelog to version 3.8.1
devin-ai-integration[bot] Dec 10, 2025
b3dd327
Merge origin/main and resolve changelog conflict
devin-ai-integration[bot] Dec 10, 2025
45d7470
fix: bump webhook responses changelog to version 3.9.0 (feat requires…
devin-ai-integration[bot] Dec 10, 2025
3fd5937
update changelog and version file
sbawabe Dec 10, 2025
6feffaf
Merge branch 'main' of https://github.com/fern-api/fern into devin/17…
sbawabe Dec 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { V2WebhookExample, Webhook, WebhookPayload } from "@fern-api/ir-sdk";
import { HttpResponse, V2WebhookExample, Webhook, WebhookPayload } from "@fern-api/ir-sdk";

import { AbstractOperationConverter } from "./AbstractOperationConverter";

Expand Down Expand Up @@ -75,6 +75,8 @@ export class WebhookConverter extends AbstractOperationConverter {
return undefined;
}

const responses = this.convertWebhookResponses();

return {
audiences:
this.context.getAudiences({
Expand All @@ -89,6 +91,7 @@ export class WebhookConverter extends AbstractOperationConverter {
method: httpMethod,
headers,
payload,
responses: responses.length > 0 ? responses : undefined,
examples: [],
availability: this.context.getAvailability({
node: this.operation,
Expand All @@ -108,6 +111,44 @@ export class WebhookConverter extends AbstractOperationConverter {
};
}

private convertWebhookResponses(): HttpResponse[] {
const responses: HttpResponse[] = [];

if (this.operation.responses == null) {
return responses;
}

for (const [statusCode, response] of Object.entries(this.operation.responses)) {
// Check for wildcard status codes like 4XX or 5XX
const isWildcard = /^\d[Xx]{2}$/.test(statusCode);
let statusCodeNum: number;

if (isWildcard) {
// Convert wildcard to base value (e.g., "4XX" -> 400, "5XX" -> 500)
// We know statusCode[0] exists because the regex matched
statusCodeNum = parseInt(statusCode.charAt(0)) * 100;
} else {
statusCodeNum = parseInt(statusCode);
if (isNaN(statusCodeNum)) {
continue;
}
}

this.context.resolveMaybeReference({
schemaOrReference: response,
breadcrumbs: [...this.breadcrumbs, "responses", statusCode]
});

responses.push({
statusCode: statusCodeNum,
isWildcardStatusCode: isWildcard ? true : undefined,
body: undefined
});
}

return responses;
}

private getWebhookV2ExamplesFromRequestBodyV2Examples(
requestBodyV2Examples: Record<string, unknown>
): Record<string, V2WebhookExample> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,11 @@
},
"type": "reference"
},
"responses": [
{
"statusCode": 200
}
],
"examples": [],
"v2Examples": {
"autogeneratedExamples": {},
Expand Down
10 changes: 9 additions & 1 deletion packages/cli/cli/versions.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
# yaml-language-server: $schema=../../../fern-versions-yml.schema.json
- changelogEntry:
- summary: |
Propagate webhook responses (e.g., 204, 400, 500 status codes) from OpenAPI specs to the IR. Webhook endpoints can now define expected response status codes and descriptions, which are captured in the IR for use by generators and documentation.
type: feat
irVersion: 62
createdAt: "2025-12-10"
version: 3.9.0

- changelogEntry:
- summary: |
Include -y flag for the upgrade for non-interactive environments.
type: feat
irVersion: 63
irVersion: 62
createdAt: "2025-12-10"
version: 3.8.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43383,6 +43383,7 @@ exports[`ir > {"name":"webhooks"} 1`] = `
}
]
},
"responses": null,
"examples": null,
"v2Examples": null,
"availability": null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1387,6 +1387,7 @@
},
"docs": null
},
"responses": null,
"examples": null,
"v2Examples": null,
"availability": null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5175,6 +5175,7 @@
},
"docs": null
},
"responses": null,
"examples": null,
"v2Examples": null,
"availability": null,
Expand Down Expand Up @@ -5277,6 +5278,7 @@
},
"docs": null
},
"responses": null,
"examples": null,
"v2Examples": null,
"availability": null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4016,6 +4016,7 @@
},
"docs": null
},
"responses": null,
"examples": null,
"v2Examples": null,
"availability": null,
Expand Down Expand Up @@ -4118,6 +4119,7 @@
},
"docs": null
},
"responses": null,
"examples": null,
"v2Examples": null,
"availability": null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1411,6 +1411,7 @@
},
"docs": null
},
"responses": null,
"examples": null,
"v2Examples": null,
"availability": null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export function convertWebhookGroup({
)
: [],
payload: convertWebhookPayloadSchema({ payload: webhook.payload, file }),
responses: undefined,
examples:
webhook.examples != null
? convertWebhookExamples({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ export const V62_TO_V61_MIGRATION: IrMigration<
errors: resolveErrorDeclarationConflicts(v62.errors),
services: Object.fromEntries(
Object.entries(v62.services).map(([key, service]) => [key, convertHttpService(service)])
)
),
webhookGroups: stripResponsesFromWebhooks(v62.webhookGroups)
};
}
};
Expand All @@ -67,8 +68,8 @@ function resolveErrorDeclarationConflicts(
const isWildcard = errorDeclaration.isWildcardStatusCode === true;

if (!isWildcard) {
// For non-wildcard errors, set isWildcardStatusCode to undefined since v61 didn't use it
const { isWildcardStatusCode, ...v61ErrorDeclaration } = errorDeclaration;
// For non-wildcard errors, strip headers and isWildcardStatusCode since v61 didn't have them
const { isWildcardStatusCode, headers, ...v61ErrorDeclaration } = errorDeclaration;
resolvedErrors[errorId] = {
...v61ErrorDeclaration,
isWildcardStatusCode: undefined
Expand All @@ -95,3 +96,18 @@ function convertHttpEndpoint(
errors: endpoint.errors
} as IrVersions.V61.http.HttpEndpoint;
}

function stripResponsesFromWebhooks(
webhookGroups: IntermediateRepresentation["webhookGroups"]
): Record<string, IrVersions.V61.webhooks.WebhookGroup> {
const result: Record<string, IrVersions.V61.webhooks.WebhookGroup> = {};

for (const [groupId, webhookGroup] of Object.entries(webhookGroups)) {
result[groupId] = webhookGroup.map((webhook) => {
const { responses, ...v61Webhook } = webhook;
return v61Webhook as IrVersions.V61.webhooks.Webhook;
});
}

return result;
}
Original file line number Diff line number Diff line change
Expand Up @@ -1193,6 +1193,23 @@
},
"type": "reference",
},
"responses": [
{
"body": undefined,
"isWildcardStatusCode": undefined,
"statusCode": 204,
},
{
"body": undefined,
"isWildcardStatusCode": undefined,
"statusCode": 400,
},
{
"body": undefined,
"isWildcardStatusCode": undefined,
"statusCode": 500,
},
],
"v2Examples": {
"autogeneratedExamples": {
"paymentSessionsPaymentSessionCompletedWebhookExample": {
Expand Down
2 changes: 1 addition & 1 deletion packages/ir-sdk/fern/apis/ir-types-latest/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
62.1.0
62.2.0
17 changes: 17 additions & 0 deletions packages/ir-sdk/fern/apis/ir-types-latest/changelog/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [v62.2.0] - 2025-12-10
- Fix: Propogate webhook responses from OpenAPI to IR

## [v62.1.0] - 2025-11-25

- Feature: Add `isWildcardStatusCode` field to IR for 4XX/5XX wildcard status code support
- Feature: Add optional `apiPlayground` field to `HttpEndpoint` to control API playground visibility via `x-fern-playground-enabled` extension
- Feature: Add support for preserving error response headers in IR
- Feature: Add refresh token endpoint option to inferred auth
- Feature: Add service-level docs support (docs field on `HttpService`)

## [v62.0.0] - 2025-11-04

- Feature: Add file upload examples support to IR (breaking change - adds new union variant to `ExampleRequestBody`)
- Feature: Add support for parsing minItems and maxItems from OpenAPI array schemas (`ListValidationRules`)
- Feature: Add optional `postmanCollectionLink` field to `EndpointSnippetRequest` for API reference configuration

## [v61.7.0] - 2025-10-31

- Feature: Add GenerationMetadata to IR
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ types:
method: WebhookHttpMethod
headers: list<http.HttpHeader>
payload: WebhookPayload
responses: optional<list<http.HttpResponse>>
examples: optional<list<ExampleWebhookCall>>
v2Examples: optional<examples.V2WebhookExamples>

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading