Changelog

Changes to the Flint API, SDKs, and docs

Newest first. A change that alters a request or response shape ships as a new API version, and your integration keeps its pinned version until you upgrade it. New endpoints, fields, and events are listed once a week. The upgrade guide covers pinning, testing a newer version, and rolling back. Follow changes with the RSS feed.
  • API

New in the API: week of October 5, 2026#

634 additions across Orders, Subscription plans, and 36 more areas. These are additions, so nothing you already use needs to change.

Orders
81 additions
Subscription plans
16 additions
Customer account
15 additions
Merchants
12 additions
  • Endpoint

    Get merchant

  • Endpoint

    Update merchant

  • Request field
    iconon PATCH /v1/merchant

    A square image, at least 128 by 128 pixels, shown where the store needs a small mark: browser tabs and compact headers.

  • Field

    A square image, at least 128 by 128 pixels, shown where the store needs a small mark: browser tabs and compact headers.

  • Error code

    The image's dimensions don't fit what this image is for: a merchant icon must be square and at least 128 by 128 pixels.

  • Error code

    A merchant address field is too long, or the country is not a two-letter country code.

  • Error code

    The organization_id is empty or identifies a deleted organization.

  • Error code

    The support email address is not valid.

Inventory
4 additions
Promotions
27 additions
Invoices
26 additions
Gift cards
12 additions
  • Endpoint

    Create a gift card funding disposition

  • Query parameter
    created_afteron GET /v1/gift-card-loads

    RFC3339 lower bound for created_at.

  • Query parameter
    created_beforeon GET /v1/gift-card-loads

    RFC3339 upper bound for created_at.

  • Query parameter
    created_afteron GET /v1/gift-card-notifications

    RFC3339 lower bound for created_at.

  • Query parameter
    created_beforeon GET /v1/gift-card-notifications

    RFC3339 upper bound for created_at.

  • Query parameter
    created_afteron GET /v1/gift-card-redemptions

    RFC3339 lower bound for created_at.

  • Query parameter
    created_beforeon GET /v1/gift-card-redemptions

    RFC3339 upper bound for created_at.

  • Query parameter
    posted_afteron GET /v1/gift-card-transactions

    RFC3339 lower bound for posted_at.

Subscriptions
8 additions
Returns
1 addition
Fulfillment records
79 additions
  • Request field
    courier_support_phoneon PATCH /v1/fulfillments/{fulfillment_id}

    Buyer-safe support number for the courier or merchant fleet.

  • Request field
    reason_messageon POST /v1/fulfillments/{fulfillment_id}/transitions

    Your note explaining this transition.

  • Request field
    reason_messageon POST /v1/fulfillments/{fulfillment_id}/transitions

    Your note explaining this transition.

  • Request field
    reason_messageon POST /v1/fulfillments/{fulfillment_id}/transitions

    Your note explaining this transition.

  • Request field
    reason_messageon POST /v1/fulfillments/{fulfillment_id}/transitions

    Your note explaining this transition.

  • Request field
    reason_messageon POST /v1/fulfillments/{fulfillment_id}/transitions

    Your note explaining this transition.

  • Request field
    reason_messageon POST /v1/fulfillments/{fulfillment_id}/transitions

    Your note explaining this transition.

  • Request field
    reason_messageon POST /v1/fulfillments/{fulfillment_id}/transitions

    Your note explaining this transition.

Payment links
74 additions
Refunds
50 additions
Settings
43 additions
Payments
28 additions
  • Query parameter
    dispute_statuson GET /v1/payment-intents

    Exact match on dispute_status.

  • Query parameter
    refund_statuson GET /v1/payment-intents

    Exact match on refund_status.

  • Error code

    The ACH debit confirmation token is missing the billing name or billing email.

  • Error code

    The ACH debit confirmation token does not include the buyer's online mandate acceptance.

  • Error code

    The amount is below the minimum allowed for the payment option.

  • Error code

    The amount exceeds the maximum allowed for the payment option.

  • Error code

    The payment processor's amount for this payment intent no longer matches Flint's record.

  • Error code

    amount_money cannot change once a payment source is attached or confirmation is attempted, or when an order owns the payment intent.

Products
26 additions
Risk controls
17 additions
Delivery configuration
15 additions
Organizations
11 additions
Webhooks
11 additions
Checkout sessions
10 additions
Modifiers
10 additions
Bundles
8 additions
Onboarding
8 additions
API request logs
7 additions
Partner apps
7 additions
Delivery previews
3 additions
  • Field

    The delivery question this preview answers. - `pickup_locations`: Lists the checkout session's pickup locations and whether each can supply its items.

  • Field

    The delivery question this preview answers. - `delivery_options`: Evaluates delivery methods and prices for the supplied items and buyer location.

  • Values

    pickup_location_dependency_failurepickup_location_geography_unavailablepickup_location_inactivepickup_location_inventory_unavailable

Partner OAuth
3 additions
Delivery quotes
2 additions
Money movement
2 additions
Credit notes
1 addition
Customers
1 addition
Delivery selections
1 addition
Devices
1 addition
Disputes
1 addition
Payment methods
1 addition
Sandboxes
1 addition
Errors
11 additions
  • API

New in the API: week of September 28, 2026#

200 additions across Gift cards, Customer account, and 21 more areas. These are additions, so nothing you already use needs to change.

Related: Codes for saved details default to the auto channel, Delivery choice groups name their method types, Delivery quotes name required recipient fields before an address, Delivery recipient details are checked at payment, Quotes offer delivery and pickup windows only while they can be chosen, Exact ZIP codes match verified addresses, Pickup search takes the buyer's current choice and lists stores that track no inventory, Request bodies up to 1 MiB, State conditions match the state a buyer sends

Gift cards
32 additions
Customer account
26 additions
Orders
43 additions
  • Endpoint
  • Endpoint

    Apply a gift card to an order

  • Endpoint
  • Request field
    gift_card_recipienton PATCH /v1/orders/{order_id}/line-items/{order_line_item_id}

    Replaces the recipient of an unfunded gift card purchase.

  • Request field
    accepted_gift_card_allocationon POST /v1/orders/{order_id}/pay

    Accept the exact gift_card_estimate returned on the current order, including all selected cards and both totals.

  • Request field
    accepted_gift_card_allocationon POST /v1/orders/{order_id}/pay

    Accept the exact gift_card_estimate returned on the current order, including all selected cards and both totals.

  • Request field
    save_payment_method_phoneon POST /v1/orders/{order_id}/pay

    A US or Canadian mobile phone number in E.164 format, such as +14155552671, that confirms a card saved while the checkout acts for no customer, or for the customer whose email the buyer confirmed in it.

  • Request field
    save_payment_method_phoneon POST /v1/orders/{order_id}/pay

    A US or Canadian mobile phone number in E.164 format, such as +14155552671, that confirms a card saved while the checkout acts for no customer, or for the customer whose email the buyer confirmed in it.

Checkout sessions
16 additions
Products
14 additions
Refunds
13 additions
Webhooks
6 additions
  • Values

    gift_card_load.createdgift_card_load.updatedgift_card_notification.createdgift_card_notification.updatedgift_card_redemption.createdgift_card_redemption.updated

  • Values

    gift_card_load.createdgift_card_load.updatedgift_card_notification.createdgift_card_notification.updatedgift_card_redemption.createdgift_card_redemption.updated

  • Values

    gift_card_load.createdgift_card_load.updatedgift_card_notification.createdgift_card_notification.updatedgift_card_redemption.createdgift_card_redemption.updated

  • Values

    gift_card_load.createdgift_card_load.updatedgift_card_notification.createdgift_card_notification.updatedgift_card_redemption.createdgift_card_redemption.updated

  • Values

    gift_card_load.createdgift_card_load.updatedgift_card_notification.createdgift_card_notification.updatedgift_card_redemption.createdgift_card_redemption.updated

  • Values

    gift_card_load.createdgift_card_load.updatedgift_card_notification.createdgift_card_notification.updatedgift_card_redemption.createdgift_card_redemption.updated

Subscriptions
4 additions
Delivery previews
2 additions
Delivery quotes
2 additions
Delivery selections
2 additions
Inventory
2 additions
Invoices
2 additions
Reports
2 additions
Return operations
2 additions
Returns
2 additions
Merchants
1 addition
Onboarding
1 addition
Payment links
1 addition
Settings
1 addition
Subscription plans
1 addition
Webhook events
7 additions
Errors
18 additions
  • Breaking change
  • API
  • Checkout

Codes for saved details default to the auto channel#

POST /v1/checkout-sessions/{checkout_session_id}/customer-verifications with purpose set to use_saved_payment_methods and no channel now uses "channel": "auto", which hosted checkout sends as the buyer types their email. Flint sends the code the way the buyer saved their details:

  • Details saved with a mobile phone number: Flint texts the code to that number, and the response has "channel": "sms" and phone_last_digits.
  • Details saved only by email: Flint emails the code, and the response has "channel": "email".
  • No saved details, or a cap reached: Flint sends nothing and returns 409 with CUSTOMER_VERIFICATION_NOT_SENT.

Breaking: until this release, a request without a channel emailed the code and answered the same whether or not the email had saved details. To keep that answer, send "channel": "email". A channel sent as an empty string or null now returns 400; leave the field out to use the default.

save_payment_method still defaults to email, and confirm_saved_payment_method still requires a channel. See Recognize a returning buyer.

  • API
  • Delivery
  • Checkout

Delivery choice groups name their method types#

A buyer-authenticated delivery quote showed how a choice group could be delivered only through its options, and a group has no options until the buyer gives what its methods need, such as an address. A checkout that offers only local delivery could not tell that from a shipping checkout until then.

  • Choice groups list method_types. The values are shipment, pickup, and local_delivery, each listed once, in the order the methods display. The field is on quotes, on the session's fulfillment, and in merchant-authenticated responses.
  • A type stays listed while its methods need input or cannot serve the current input, so a page can name what does not reach the buyer. options lists what the buyer can choose now.
  • A method whose type the group's items do not allow is left out. The list is [] when no method can serve the group.

See Build your own checkout.

  • API
  • Delivery
  • Checkout

Delivery quotes name required recipient fields before an address#

A quote listed a method's required recipient fields in input_requirements only once the method had an option. Before the buyer gave an address, a local delivery that needs the recipient's phone listed only the address, although the checkout session named recipient.phone before any quote existed. An Apple Pay or Google Pay sheet opened from that quote did not ask for a phone, so payment then failed with DELIVERY_RECIPIENT_REQUIRED.

  • A method waiting on the buyer's address or store lists the recipient fields it requires, with purpose selection, next to the quote requirement for the address. The same applies while the buyer must correct an address Flint could not use.
  • Those requirements name the method's choice group and have no delivery_option_ids. A quote that prices the method lists the requirement for its option instead, as before.
  • A method that cannot serve a usable address lists none. A choice group's own input_requirements still lists only what the group needs before it can be priced.

The change applies to delivery quotes, the checkout session's fulfillment, and delivery previews. See Delivery quotes.

  • API
  • Delivery
  • Checkout

Delivery recipient details are checked at payment#

Selecting a delivery option no longer fails when the recipient is missing a field the option requires, such as a phone for local delivery. Apple Pay and Google Pay reveal the buyer's name and phone only after the buyer approves the payment sheet, so a wallet flow can now select delivery from the partial address first and add the recipient afterwards.

  • Delivery selections carry input_requirements. Each entry is a required recipient field the selection is still missing, with the same delivery_input_requirement_id the quote gave that option. It is [] when nothing is missing.
  • Paying the order returns 400 DELIVERY_RECIPIENT_REQUIRED while a required field is missing, before any payment is attempted. param names the first field, such as delivery_selection.recipient.phone, and remediation.missing_or_invalid_fields lists all of them.
  • To add the fields, select the same choices from the same quote with the full recipient, and send the current selection's ID as expected_delivery_selection_id. The price does not change.

A malformed email or phone you do send is still rejected when you select, with DELIVERY_REQUEST_INVALID. An integration that sends the required fields when it selects sees no difference. If yours counted on the selection rejecting a missing field, read input_requirements after selecting, or handle DELIVERY_RECIPIENT_REQUIRED from POST /v1/orders/{order_id}/pay. See Delivery selections.

  • API
  • Delivery
  • Checkout

Quotes offer delivery and pickup windows only while they can be chosen#

A schedule_window method offers its windows in each option's offered_windows. Until this release a quote also offered the part of a window already under way, starting and expiring at the moment of the quote, so choosing it failed with DELIVERY_WINDOW_EXPIRED. A window could also be chosen until it started, whatever the method's preparation_lead_time_seconds.

  • Every offered window can be chosen. A window's expires_at is preparation_lead_time_seconds before it starts, or the same-day cutoff when that is earlier, and a quote offers only windows whose expires_at is still ahead. With no lead time, a window can be chosen until it starts.
  • A window already under way is not offered. The first window is the next one the lead time allows, so start_at and end_at are always the times you configured.
  • A chosen window ends the selection at its expires_at. Pay before then, or quote and select again.

A method with one long window a day, such as store hours, now offers the next day's window once the day's window has started. To keep taking orders through the day, split it into shorter windows. See Delivery options.

  • API
  • Delivery

Exact ZIP codes match verified addresses#

Address verification returns a full US address with its ZIP+4, such as 07030-5788. Until this release a postal_code condition with an exact value such as 07030 compared the whole code, so it never matched a verified address: a method limited to exact ZIP codes read as outside the delivery area everywhere, while the same codes as prefix values worked. That applied to zones, method eligibility, rate-table when conditions, and pickup searches by buyer_location.

  • A five-digit ZIP code matches the ZIP+4 codes within it. 07030 matches 07030, 07030-5788, and 070305788. This applies to ZIP codes in the US and in US territories, such as Puerto Rico.
  • A ZIP+4 value matches only that ZIP+4. 07030-5788 does not match 07030 or 07030-5789.
  • Prefixes and other countries are unchanged. A prefix value still matches every code that starts with it, and codes outside the US compare whole, in uppercase without spaces or hyphens.

Check any method that excludes ZIP codes with not. An address in an excluded five-digit ZIP was not excluded before when verification returned its ZIP+4. It is now. See Delivery configuration.

  • API
  • Delivery
  • Checkout

Pickup search takes the buyer's current choice and lists stores that track no inventory#

POST /v1/checkout-sessions/{checkout_session_id}/query-pickup-availability had two problems that left buyers without stores to choose from.

  • The search takes the current delivery selection. A search that sent the checkout's current expected_delivery_selection_id returned 409 DELIVERY_PICKUP_AVAILABILITY_CHANGED, and only a search that named no selection answered, so a buyer who had chosen a store could not look for another. The search now compares the ID with the selection GET .../delivery-selections/current returns, like quote creation does, and does not change the choice. Send null only when the checkout has no selection: naming none while one is current now returns the same 409.
  • Stores without inventory allocation are listed. The search left out every store whose inventory.allocation_status was not active, although quote creation priced pickup at those stores for items without tracked inventory. A store now needs allocation only to supply items with tracked inventory. For those items, a store without it is listed with an unavailable outcome and inventory_insufficient, and merchant-authenticated searches name it in merchant_diagnostics with PICKUP_LOCATION_INVENTORY_UNAVAILABLE.

See Delivery configuration.

  • API
  • Errors

Request bodies up to 1 MiB#

Until this release a request body over 8 KB was refused before it reached the API. The response was an HTML 403 Forbidden page with no request_id, so an order with a few dozen line items or a delivery method with a week of hourly windows could not be created.

  • Bodies up to 1 MiB (1,048,576 bytes) are accepted. This is the limit on every endpoint unless its reference names a lower one.
  • A larger body returns 413 in the standard error envelope, with type set to invalid_request_error, code set to REQUEST_BODY_TOO_LARGE, and a message that states the limit. REQUEST_BODY_TOO_LARGE replaces RESOURCE_LIMIT_EXCEEDED as the code for an oversized body.
  • Split a larger write into several requests. For example, create an order with its first line items and add the rest with POST /v1/orders/{order_id}/line-items.

See Error handling.

  • API
  • Delivery

State conditions match the state a buyer sends#

state conditions store ISO 3166-2 codes such as US-NY, while buyers, address forms, Apple Pay, Google Pay, and address validation send the state as NY. Until this release Flint compared the two as written, so a state condition matched only a state sent as US-NY, and address validation rewrites that to NY for a full address. That applied to zones, to method eligibility, to rate-table when conditions, and to pickup searches by buyer_location.

  • Matching reads the address's state as a subdivision of its country. NY, ny, US-NY, and New York in a US address all match US-NY. Outside the US and Canada, send the subdivision code, with or without the country prefix. A state that names no subdivision of the address's country matches no state condition.
  • Conditions accept two-letter US and Canadian codes. Send NY or ON and Flint stores US-NY or CA-ON, so reads return the ISO 3166-2 code. NY and US-NY in the same list are rejected as duplicates. Other countries still need the full code, such as DE-BY.

Check any method that excludes states with not. A zone such as "the US but not US-AK or US-HI" excluded no one before, so its methods were offered in Alaska and Hawaii. They no longer are. See Delivery configuration.

  • Breaking change
  • API
  • Checkout

Checkout sessions always collect an order#

Every checkout session now collects an order, and pays through it. POST /v1/checkout-sessions takes exactly one of order_id, quick_pay_item, or subscription_plan_id.

Breaking: payment_intent_id is no longer a create field, and a request that sends it returns 400 with UNKNOWN_FIELD. Checkout sessions no longer carry a payment_intent_id field; payment_intent_ids still lists the order's PaymentIntents. A checkout session credential no longer reads or confirms a standalone PaymentIntent, and the error codes for PaymentIntent checkouts, such as PAYMENT_INTENT_CHECKOUT_ALREADY_EXISTS, are retired.

To charge an amount on a Flint-hosted page, create the session with quick_pay_item, and Flint creates a one-line order for it. To collect a PaymentIntent you create on its own, use Stripe Elements on your page and confirm through Flint, as Server-confirmed payments describes.

A Return resolution offers a checkout session only for the balance of its replacement Order. A correction that would leave the buyer owing money is rejected, as Return resolutions describes.

  • API

New in the API: week of September 21, 2026#

78 additions across Checkout sessions, Refunds, and 10 more areas. These are additions, so nothing you already use needs to change.

Related: Checkout sessions always collect an order

Checkout sessions
20 additions
Refunds
14 additions
Orders
12 additions
Money movement
7 additions
Fulfillment records
4 additions
Customer account
3 additions
  • Query parameter
    usageon GET /v1/me/payment-methods

    Filter by usage: off_session payment methods can be charged without the buyer; on_session ones were saved by buyers for faster checkout.

  • Request field
    typeon POST /v1/me/payment-methods

    string

  • Error code

    A subscription that is not canceled still uses the payment method.

Invoices
2 additions
Payment methods
2 additions
  • Query parameter
    usageon GET /v1/payment-methods

    Filter by usage: off_session payment methods can be charged without the buyer; on_session ones were saved by buyers for faster checkout.

  • Field

    When Flint may charge the payment method. off_session payment methods can pay subscriptions, automatic invoices, and other charges without the buyer, and can be a customer's default. on_session payment methods were saved by the buyer in checkout for faster checkout at this merchant; Flint charges them only in checkouts the buyer completes and refuses them for any charge without the buyer and as a default.

Settings
2 additions
Onboarding
1 addition
  • Error code

    The request payload or query parameters did not pass validation.

Payment links
1 addition
Errors
10 additions
  • API
  • Invoices
  • Refunds

Refund a credit note on a paid invoice#

A credit note can now return money. Until this release a note could only be allocated against an outstanding balance, so a correction to a paid invoice meant a credit note for the paperwork and a separate refund against the order. Now the note creates the refund, and the refund stays linked to it.

To issue a draft and refund it in one call, add refund to POST /v1/credit-notes/{credit_note_id}/issue. The response keeps the credit note at data and adds the refund at data.refund. For a note that is already issued, call POST /v1/credit-notes/{credit_note_id}/refunds, which returns the Refund resource. Both accept amount_money, reason, and reason_message. Leave amount_money out to refund all available credit. The money goes back to the original payment methods; payments you recorded manually are not eligible.

Both calls require a caller-chosen Idempotency-Key, and both need commerce.credit_notes.write and commerce.refunds.write. Flint keeps the key for the life of the refund. To recover a response you lost, call GET /v1/credit-notes/{credit_note_id}/refunds?idempotency_key=..., which needs both read scopes.

Credit notes carry two new fields. pending_refund_money reserves credit while a refund is unresolved, and refunded_money records what succeeded. Both reduce unallocated_money, and a failed or canceled refund releases its amount. Refunds created this way carry credit_note_id and invoice_id, and they fire the existing refund.* events. The invoice stays paid, with refund_status and refunded_money tracking the refund as before.

A credit note cannot be voided while a refund on it is pending or after one succeeds; the call returns CREDIT_NOTE_HAS_ALLOCATIONS. A refund larger than the available credit returns CREDIT_NOTE_REFUND_EXCEEDS_BALANCE, and an ineligible invoice or note returns CREDIT_NOTE_REFUND_INVALID.

These changes are additive. See Refund a paid invoice for the walkthrough.

  • API
  • Invoices
  • Tax

Invoice late fees and automatic tax on invoices#

Late fees are now part of the invoice balance. invoice.late_fee_due still fires after the grace period on the invoice's payment term, and it remains a notice. To charge it, call POST /v1/invoices/{invoice_id}/late-fees, which assesses the frozen policy against the current unpaid principal, once per invoice or per overdue schedule entry. Send invoice_schedule_entry_id for a scheduled invoice and {} for an unscheduled one.

POST /v1/invoices/{invoice_id}/late-fees/{invoice_late_fee_id}/waive waives the unpaid remainder and requires a reason, which is visible only to you. A waiver leaves collected money in place; refund it through the Refunds API.

Invoice responses carry late_fees, with each fee's calculation inputs, assessed amount, paid amount, waived amount, and outstanding amount. An assessed fee raises the outstanding balance and appears as a dated addendum on the hosted invoice and the PDF. The issued line items, tax, and original total do not change. Subscribe to invoice.late_fee_assessed and invoice.late_fee_waived to track the balance, and late_fee_assessed and late_fee_waived join the invoice event timeline.

This release supports fixed and percentage policies, without recurring fees, compounding, or tax on the fee.

Quaderno-connected automatic tax also works on invoices now. Issue freezes the calculation, and the invoice takes one payment for its full balance: a schedule for less than the balance fails with AUTOMATIC_TAX_INVOICE_INSTALLMENTS_UNSUPPORTED, and a partial payment fails with AUTOMATIC_TAX_PARTIAL_PAYMENT_UNSUPPORTED. Editing the backing order after issue fails collection with INVOICE_TAX_SNAPSHOT_STALE; void the invoice and issue it again. Use external tax for a deposit, installments, or a balance collected in pieces.

  • Breaking change
  • API

API version 2026-09-07#

Balance transactions report fees as positive charges that match the payment's processing_fee_money, name their timestamp occurred_at, and identify the related resource by its own ID field. Tax categories split into line_item_tax_category for items and charge_tax_category for charges, so the field name tells you which set of values applies.

  • Your integrationKeeps working as it does today. Nothing moves to 2026-09-07 until you upgrade.
  • Affects544 endpoints and 2 webhook events. See the ones you use
  • Upgrade byNo deadline. 2026-02-01 is supported until at least September 7, 2028.
  • Roll backFor 72 hours after you switch, the Versions screen can restore your previous version.

What changes

  1. Balance transaction fee charges are positive and fee credits are negative.

    Response and request shape
    Before (2026-02-01)
    {
      "amount_money": {
        "amount": 5000,
        "currency": "USD"
      },
      "fee_money": {
        "amount": -175,
        "currency": "USD"
      },
      "net_money": {
        "amount": 4825,
        "currency": "USD"
      }
    }
    After (2026-09-07)
    {
      "amount_money": {
        "amount": 5000,
        "currency": "USD"
      },
      "fee_money": {
        "amount": 175,
        "currency": "USD"
      },
      "net_money": {
        "amount": 4825,
        "currency": "USD"
      }
    }
    What to do
    Read a positive fee_money as a fee charged and a negative one as a fee returned. net_money is unchanged.
  2. Balance transactions use occurred_at for the transaction timestamp.

    Response and request shape
    Before (2026-02-01)
    {
      "balance_transaction_id": "btxn_test",
      "created_at": "2026-09-06T12:34:56Z"
    }
    After (2026-09-07)
    {
      "balance_transaction_id": "btxn_test",
      "occurred_at": "2026-09-06T12:34:56Z"
    }
    What to do
    Use occurred_at instead of created_at.
  3. Tax categories use line_item_tax_category for items and charge_tax_category for charges.

    Response and request shape
    Before (2026-02-01)
    {
      "tax_category": "prepared_food"
    }
    After (2026-09-07)
    {
      "line_item_tax_category": "prepared_food"
    }
    What to do
    Replace tax_category with line_item_tax_category on product variants, modifiers, bundles, and line item taxes, and with charge_tax_category on delivery methods and charge taxes.
    Affects

    544 endpoints across 55 resources, most in Customer account (56), Inventory (31), Delivery configuration (29), Orders (29).

How to upgrade

  1. Read your impact report on the Versions screen. It lists the routes and webhook events you use that change.
  2. Test in test mode: send Flint-Version: 2026-09-07, or install the SDK release built for it.
  3. Move your merchant default on the Versions screen.
  4. Move webhook endpoints and partner apps that pin an older version.

Read the upgrade guide

  • Breaking change
  • API
  • Inventory

Shared money inputs and inventory tracking names#

Money inputs use Money: an integer amount in minor units and a required currency. Delivery pricing maps now require each amount's currency to match its map key, for example "USD": {"amount": 900, "currency": "USD"}. Requested tips and flat order taxes still require an amount of at least 1 minor unit.

Breaking: ad hoc order lines use inventory_tracking instead of inventory_requirement. Set it explicitly to not_tracked or tracked. Order line snapshots expose the same setting at inventory_snapshot.inventory_tracking. Validation errors use INVENTORY_TRACKING_REQUIRED and INVENTORY_TRACKING_INVALID.

For tracked ad hoc lines, each inventory_demands entry accepts only inventory_item_id and quantity_per_line_item_unit. Bundle component and component snapshot IDs remain available on responses. The catalog inventory relationship revision is no longer part of the public response.

  • Breaking change
  • API
  • Inventory

Multi-location inventory, allocation, and reservations#

Inventory has its own API. Stock is tracked per location, demand is routed across locations, and checkout holds real claims instead of decrementing a counter.

  • Inventory API: inventory items and per-location levels, adjustments, safety stock, policies, transfers, counts, and merchant-owned reservations. Read levels to inspect stock; create a reservation when your integration needs to hold it.
  • Locations API: create and manage locations, publish their geography, and enable them for inventory. Identity, geography, and the inventory block are versioned independently so concurrent writes cannot silently overwrite each other.
  • Allocation policies: rank locations into priority groups to decide which one serves demand. Single-location merchants can skip policies entirely and route to a fixed location.
  • New webhook events use the inventory. prefix, alongside order.inventory_exception.created and order.inventory_exception.resolved. See the event catalog.

Breaking: product variants no longer carry their own stock count. quantity_available and enforce_inventory_limit have been removed from ProductVariant. A variant now declares inventory_tracking (not_tracked or tracked) and points inventory_item_id at an inventory item whose quantities live on per-location levels. Tracking is never inferred from a product being physical, so a variant you do not explicitly mark tracked sells without a stock check.

Idempotency keys are required on quantity-changing commands. Adjustments and reservation transitions reject a request with no Idempotency-Key. Flint will not generate one, because a generated key cannot protect the case that matters: the request succeeded and you never received the response. Reusing a key with identical input returns the original result and its original level projections.

  • Breaking change
  • Payments
  • API

One all-in processing fee on every payment#

Payments now report a single Flint processing fee, and the fields around it are provider-neutral.

  • processing_fee_money on payment intents replaces platform_fee_money. It is Flint's complete all-in price to process the payment, not a provider cost with a markup on top, so your net is captured_money minus this one field. The fee is final at card capture or ACH success; canceled payments and failures before success have none, and refunds do not return or revise it.
  • Balance transaction fee_money is documented as Flint's own fee on the movement. Refund, dispute, and return entries carry no Flint fee; an instant payout carries its own.
  • processor_fee and flint_fee balance transaction types are no longer part of the public ledger. What Flint pays its providers is Flint's cost and never appears as a deduction on your payments.

New Processing fees and Reconciliation guides cover the fee lifecycle and matching deposits back to the ledger.

  • Docs
  • API

New developer docs with a generated API reference#

The developer docs have been rebuilt:

  • Generated API reference: every endpoint is now documented from the same contract the server runs, with request and response schemas, realistic examples, and cURL plus Node SDK samples generated from that contract, so they do not drift.
  • Webhook event catalog at /docs/webhooks/events and an error code catalog, both generated from server code.
  • Agent-ready docs: append .md to any page URL for raw Markdown, fetch /llms.txt or /llms-full.txt, or connect your editor to the docs MCP server at https://developers.withflintpay.com/mcp.
  • Dark mode and a refreshed design that matches the Flint dashboard.