docs(openapi): Autofix OpenAPI spec validation errors#2794
Conversation
Fix 1: Webhook object no longer requires requestUrl
Error: Jul 16 10:34:11 apify-api SOFT_FAIL {"errors":[{"errorCode":"required.openapi.validation","message":"must have required property 'requestUrl'","path":"/response/data/requestUrl"}],"method":"GET","msg":"Response OpenAPI validation error","statusCode":200.0,"url":"/v2/webhooks/{webhookId}"}
Files: apify-api/openapi/components/schemas/webhooks/Webhook.yaml:2
Root cause: requestUrl is optional in apify-core and enforced only for webhooks with actionType HTTP_REQUEST. Webhooks with other action types (Slack message, Google Mail, Google Drive, GitHub issue) are stored without requestUrl, and the API response projection (lodash pick) omits missing keys, so GET /v2/webhooks/{webhookId} legitimately returns a webhook object without requestUrl.
Reference: https://github.com/apify/apify-core/tree/446d6faa5a503ddb64447c4b6b758a811b11b397/src/packages/schemas/src/webhooks.ts#L315
Fix 2: Webhook summary in webhook dispatch allows null requestUrl
Error: Jul 21 03:20:22 apify-api SOFT_FAIL {"errors":[{"errorCode":"type.openapi.validation","message":"must be string","path":"/response/data/webhook/requestUrl"},{"errorCode":"type.openapi.validation","message":"must be null","path":"/response/data/webhook"},{"errorCode":"anyOf.openapi.validation","message":"must match a schema in anyOf","path":"/response/data/webhook"}],"method":"POST","msg":"Response OpenAPI validation error","statusCode":201.0,"url":"/v2/webhooks/{webhookId}/test?token=<REDACTED>"}
Files: apify-api/openapi/components/schemas/webhook-dispatches/WebhookDispatchWebhookSummary.yaml:10
Root cause: POST /v2/webhooks/{webhookId}/test embeds the stored webhook into the created dispatch and the response projection includes webhook.requestUrl. Webhook create/update accepts requestUrl as nullish, so non-HTTP webhooks can be stored with an explicit null requestUrl, which is then returned inside the dispatch's webhook summary.
Reference: https://github.com/apify/apify-core/tree/446d6faa5a503ddb64447c4b6b758a811b11b397/src/packages/zod-types/src/common/webhooks.ts#L57
Fix 3: Add 402 response to POST /v2/actor-tasks/{actorTaskId}/run-sync
Error: Jul 20 15:56:30 apify-api SOFT_FAIL {"errors":[{"message":"no schema defined for status code '402' in the openapi spec","path":"/v2/actor-tasks/{actorTaskId}/run-sync?timeout=300&memory=1024&maxItems=20&build=latest&outputRecordKey=OUTPUT&webhooks="}],"method":"POST","msg":"Response OpenAPI validation error","statusCode":402.0,"url":"/v2/actor-tasks/{actorTaskId}/run-sync?timeout=300&memory=1024&maxItems=20&build=latest&outputRecordKey=OUTPUT&webhooks="}
Files: apify-api/openapi/paths/actor-tasks/actor-tasks@{actorTaskId}@run-sync.yaml:144
Root cause: Launching a task run enforces platform usage limits which throw 402 Payment Required errors (actor memory limit, concurrent runs limit, not enough usage to run paid Actor). Sibling run-sync endpoints already document 402 via the shared PaymentRequired response component.
Reference: https://github.com/apify/apify-core/tree/446d6faa5a503ddb64447c4b6b758a811b11b397/src/packages/errors/src/errors/actor.ts#L5
Fix 4: Add 408 response to POST /v2/actor-tasks/{actorTaskId}/run-sync
Error: Jul 21 18:01:10 apify-api SOFT_FAIL {"errors":[{"message":"no schema defined for status code '408' in the openapi spec","path":"/v2/actor-tasks/{actorTaskId}/run-sync?token=<REDACTED>&outputRecordKey=OUTPUT"}],"method":"POST","msg":"Response OpenAPI validation error","statusCode":408.0,"url":"/v2/actor-tasks/{actorTaskId}/run-sync?token=<REDACTED>&outputRecordKey=OUTPUT"}
Files: apify-api/openapi/paths/actor-tasks/actor-tasks@{actorTaskId}@run-sync.yaml:152
Root cause: The run-sync handler throws run-timeout-exceeded with status 408 when the run does not reach a terminal status within the maximum synchronous wait time. The GET operation of the same path and all sibling run-sync endpoints already document 408 via the shared Timeout response component.
Reference: https://github.com/apify/apify-core/tree/446d6faa5a503ddb64447c4b6b758a811b11b397/src/api/src/routes/actor_tasks/run_sync.ts#L68
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SdZCyJ9vhtU2DKVvQYiNUD
|
🗑️ Preview for this PR was deleted. |
|
Important Action required — @Pijukatel please coordinate this docs PR with the Python API client PR linked below. Because this PR modifies the OpenAPI specification, the generated models in A companion PR has been opened in
|
|
Important Action required — @Pijukatel please coordinate this docs PR with the Python API client PR linked below. Because this PR modifies the OpenAPI specification, the generated models in The companion
|
- Updates the auto-generated Pydantic models and TypedDicts based on the proposed OpenAPI specification changes. - Based on apify-docs PR [#2794](apify/apify-docs#2794).
Summary
Autogenerated OpenAPI fixes suggestions based on validation errors generated from running API integration tests with OpenAPI validator turned on.
Error log: User-provided production
api.logexcerpt (SOFT_FAIL response validation errors, Jul 16–21, 2026). The log is not available at a public URL, so the normalized log lines are included below:apify-core version: https://github.com/apify/apify-core/commit/446d6faa5a503ddb64447c4b6b758a811b11b397
Stop reason: All 4 unique errors from the provided log that are still present on
masterare fixed. The remaining 4 unique errors in the log were already fixed onmasterby #2785 (the log lines predate that merge, see Out of scope errors). The original errors cannot be reproduced in the PR test environment (they come from production traffic: non-HTTP webhooks, platform usage limits, sync-run timeouts), so they were verified against apify-core source instead. A regression run of the integration tests with the fixed spec completed with status SUCCESS (validator run results) and its api.log contains zero response validation errors; the remaining request validation errors in that log are deliberate malformed-request tests or pre-existing request-side spec gaps unrelated to this diff.Detailed changes description
Error fixes
Webhook object no longer requires
requestUrlapify-api/openapi/components/schemas/webhooks/Webhook.yaml:2must have required property 'requestUrl'at/response/data/requestUrl,GET /v2/webhooks/{webhookId}, status 200requestUrlis optional in apify-core and enforced only for webhooks with actionTypeHTTP_REQUEST. Webhooks with other action types (Slack message, Google Mail, Google Drive, GitHub issue) are stored withoutrequestUrl, and the API response projection (lodashpick) omits missing keys, so the endpoint legitimately returns a webhook object withoutrequestUrl. A clarifying description was added to the property.Webhook summary in webhook dispatch allows null
requestUrlapify-api/openapi/components/schemas/webhook-dispatches/WebhookDispatchWebhookSummary.yaml:10must be stringat/response/data/webhook/requestUrl,POST /v2/webhooks/{webhookId}/test, status 201webhook.requestUrl. Webhook create/update acceptsrequestUrlas nullish (z.string().nullish()), so non-HTTP webhooks can be stored with an explicitnullvalue, which is then returned inside the dispatch's webhook summary. The type was widened to[string, "null"]and a clarifying description was added to the property.Add 402 response to
POST /v2/actor-tasks/{actorTaskId}/run-syncapify-api/openapi/paths/actor-tasks/actor-tasks@{actorTaskId}@run-sync.yaml:144no schema defined for status code '402' in the openapi spec,POST /v2/actor-tasks/{actorTaskId}/run-sync, status 402 (3 occurrences in the log)PaymentRequiredresponse component.Add 408 response to
POST /v2/actor-tasks/{actorTaskId}/run-syncapify-api/openapi/paths/actor-tasks/actor-tasks@{actorTaskId}@run-sync.yaml:152no schema defined for status code '408' in the openapi spec,POST /v2/actor-tasks/{actorTaskId}/run-sync, status 408run-timeout-exceededwith status 408 when the run does not reach a terminal status within the maximum synchronous wait time. The GET operation of the same path and all sibling run-sync endpoints already document 408 via the sharedTimeoutresponse component.Refactoring
None. Only shared response components (
PaymentRequired.yaml,Timeout.yaml) are re-used; no structural changes.Unfixed errors
Out of scope errors
POST /v2/actors/{actorId}/builds— no schema for status 402no schema defined for status code '402' in the openapi spec, status 402 (Jul 18 00:34:05)masterby docs(openapi): Autofix OpenAPI spec validation errors #2785 (merged Jul 20); the log line predates the merge.POST /v2/actor-tasks— no schema for status 404no schema defined for status code '404' in the openapi spec, status 404 (Jul 18 02:50:38)masterby docs(openapi): Autofix OpenAPI spec validation errors #2785; the log line predates the merge.GET /v2/actors/{actorId}—taggedBuildsbuildNumbertype errormust be stringat/response/data/taggedBuilds/{tag}/buildNumber, status 200 (Jul 20 08:15:38)masterby docs(openapi): Autofix OpenAPI spec validation errors #2785 (buildNumbermade nullable); the log line predates the merge.PUT /v2/actor-tasks/{actorTaskId}— no schema for status 409no schema defined for status code '409' in the openapi spec, status 409 (Jul 20 08:47:37)masterby docs(openapi): Autofix OpenAPI spec validation errors #2785; the log line predates the merge.Issues
Partially implements: #2286