Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
Last step of the Quotes documentation stack:
quote → order form → order. The order is what actually applies the deal.Sources, all merged:
mainorder.*webhooks, from lago-api#6134POST /orders/:id/execute, from lago-api#6162execute_at, from lago-api#6138All three are now merged, and everything here has been re-verified against
main.Changes
3 endpoints under a new
orderstag, gated on the premiumorder_formsfeature flag:GET /ordersstatus[],order_type[],execution_mode[],customer_id[],number[],order_form_number[],quote_number[],owner_id[],search_term, and anexecuted_atrangeGET /orders/{lago_id}POST /orders/{lago_id}/executeexecution_mode; synchronous2 webhooks:
order.created,order.executed.Notes for review
billing_snapshotis on the REST responses but not the webhooks. #6134 makes it opt-in onOrderSerializerand passesincludes: %i[billing_snapshot]from the controller only. That's the one place the two shapes diverge, soOrderObject(webhooks) andOrderObjectExtended(REST) split on exactly that field.billing_snapshotreusesQuoteBillingItemsfrom feat(quotes): document the Quotes REST API and webhooks #567 — it is literallyquote_version.billing_items, so the camelCase blob is documented once for the whole stack.execution_recordis documented key by key, including which keys each order type fills:invoice_idforone_off,subscription_ids/applied_coupon_ids/wallet_idsforsubscription_creation, plusterminated_subscription_idsforsubscription_amendment. Every key is always present perEXECUTION_RECORD_DEFAULTS, which the schema description states so integrators don't code around missing keys.terminated_subscription_idsis only filled when the amendment rotated immediately. A downgrade schedules the replacement and leaves the target running, so the array stays empty. Documented as such.order.executedfires on success only. A failed attempt rolls back, setsfailed, writesexecution_record.errors, and emits nothing; Lago does not retry. Both the status enum and the webhook description say so, since "no webhook" is easy to misread as "still running".executeis synchronous and idempotent (#6162). The response carries the resulting status and, on failure, the execution error, so the422body is where the reason lives rather than a later webhook. Re-executing an executed order returns it untouched; afailedorder is retried.execution_modein the body is only persisted when it differs from the stored value, which is what keeps a retry from trippingnot_editable.execute_at. The clock job runs overOrder.executable, which requires a non-nullexecute_atset at signing time via feat(order-forms): document the Order forms REST API and webhooks #568'smark_as_signed. Without it the order simply waits for an on-demand execute.422on a date the caller never sent (#6138). It only permitsexecution_mode, but supplying one that differs from the stored value routes throughOrders::UpdateService, whoseeffective_execute_atfalls back to the order's storedexecute_atand re-validates it against the deal's term. An order with noexecute_atis not bounded that way, so execution-time failure stays the backstop — both documented on the endpoint.422also coverslock_acquisition_failed, which is acodeon the error body rather than anerror_detailsentry.OrderExecutionModeEnumOrNullmirrors theCurrency/CurrencyOrNullprecedent, since the order'sexecution_modeis nullable while themark_as_signedinput's is not.redocly lintandspectral lintpass with 0 errors.One thing worth a decision
The three PRs add 18
array-params-pluralwarnings in total (5 + 5 + 8), on top of the 6 already onmain. The filter params really are singular in the API, so the only ways to clear them are to document these filters as scalars — which is valid here, the contracts accept both, but hides that they take arrays — or to relax the rule for these paths. Happy to do either; I defaulted to documenting the more capable form.🤖 Generated with Claude Code
Review fixes applied
From the OpenAPI Guardian sweep, verified against merged
main:404is not only "order not found". Thesubscription_creationandsubscription_amendmentexecutors raisenot_found_failure!for a deleted plan, charge, fixed charge, coupon, billable metric or amended subscription.record_execution_failure!has already marked the orderfailed, so a404can leave a failed order behind. Now documented.createdorder is rejected outright; that is not what the code does —BaseExecuteServiceonly short-circuits onexecuted?, and a request spec asserts afailedorder re-executes. The real limit is thatOrders::UpdateServicegates oncreated, so a failed order can be retried but not switched to anotherexecution_mode. Documented that way rather than as reported.Now also covers lago-api#6182 + #6185
Both merged to
mainas1b1c24a, and re-verified against it.422validation error viaOrders::UpdateService, while the execution itself losing it keeps returning the lock code, becauseExecuteOrderJobrelies on that error to retry a scheduled run.billing_snapshotpicks upoverrides.amountCurrencyfor free, since it reusesQuoteBillingItemsfrom feat(quotes): document the Quotes REST API and webhooks #567.OrderObjectandexecution_recordare unchanged by both PRs.