Change log
September 30 2026
The embedded checkout (
askell.js) now acceptsdefaultOffer(ordefault_offer), which pre-selects an offer when a sales channel offers more than one product. Unlikeoffer, which fixes the offer and skips the step where it is chosen, the selection stays on screen and the buyer can change it. A price or bundle template that is not in the session’soffer_catalog, or is sold out, is ignored and the widget then uses its normal default selection; apromotion_codeon the offer is applied from the start. See Embedded checkout.
September 17 2026
The payment page receipt is now itemized from the quote the sale was charged from, including the shipping fee and the total it is part of. The shipping option is chosen after the summary last fetched a quote, so that quote on its own was missing the fee.
POST /public/api/payment-pages/process_payment_and_finalize/now returnsquote— the stored quote the charge was based on, in the same shape thatPOST /public/api/payment-pages/quote/returns (includingquote_token,expires_atandpromotion). On the older path, where payment is made withoutquote_token,quoteisnulland the receipt shows the quote the page already had.
September 16 2026
Fulfillment orders can now be fulfilled in an external system. Under Settings › Shipping you choose between three options: no orders, fulfillment in Áskell, or fulfillment in an external system. With the last option, orders are still created and sent out with
fulfillment_order.*events as before, but the seller’s warehouse system books the shipment itself — so the booking button and the shipping label disappear from the order view, although orders can still be fulfilled and canceled there.Two new endpoints close the loop from the other side:
POST /api/v2/fulfillment-orders/<id>/fulfill/records the shipment (tracking_number,tracking_url,provider_order_id,carrierandweight_grams, all optional), fulfills the order, sends the customer the notification that the order is on its way and sendsfulfillment_order.fulfilled;POST /api/v2/fulfillment-orders/<id>/cancel/cancels an order. Both are idempotent, return the full order just likeGETdoes, and return409withorder_cancelledororder_fulfilledwhen the status conflicts. They are available in both fulfillment modes, so a seller who fulfills in Áskell can also automate the last step from their own system.
September 15 2026
Payment pages now calculate the price once and bind every later step to it. The quote (
POST /public/api/payment-pages/quote/) now returnsquote_tokenandexpires_at, and card sessions (Adyen/Teya),verify_cardandprocess_payment_and_finalizeaccept the token and price from the stored quote instead of recalculating the quote from browser data. The amount the customer sees, the card authorization and the first billing run are therefore always the same number, shipping fee and discounts included.A stored quote is checked against the current pricing at every step and rejected if anything has changed:
quote_changed,promotion_terms_changed,combo_eligibility_changedorinvalid_promotion_code. An expired quote, an already paid quote or another page’s quote returnsquote_expired,quote_consumed,quote_page_mismatchorquote_not_found, and the payment page sends the customer back to the payment step, where a new price is fetched. A card verified for one quote does not pay for another (quote_mismatch). The quote returnspromotionwith the code the price was calculated with, so the summary never shows a discount the charge does not carry, and the quote endpoint is limited to 120 requests per minute per IP address.Item lines,
promotion_code,shippingandzip_codeas pricing inputs onverify_card,process_payment_and_finalizeand card sessions are deprecated. They keep working for one more release for older browser clients and will be removed in the next release.The shipping fee now shows in the total before payment, both on payment pages and in the widget. Quote requests (
POST /public/api/payment-pages/quote/andPOST /api/v2/checkout-sessions/<token>/quote/) accept theshippingobject, add the fee tosubtotal_amount,tax_amountandtotal_amount, and return ashipping_feebreakdown; free shipping comes back with zeros so it can be shown as costing nothing. The free-shipping threshold (free_above_amount) is evaluated after promotion codes, as when a checkout is created, and the summaries show shipping as a separate line. Payment page card verification (verify_card) now also receivesshippinganddelivery_address, so the authorization covers the fee.The shipping fee is no longer part of the purchase amount when the first period ships no products. A trial period defers the products to the first renewal, which is then the first shipment and charges the agreed fee; the quote, checkout, card authorization and first billing run therefore all show the same amount without the fee. A trial subscription that ships a one-time item right away still pays for that shipment, and a promotion code that skips the trial period brings both the products and the fee forward.
Shipping rate tables (step four): Dropp zones (home delivery and Flytjandi) are now fetched directly from Dropp. The zones are read-only in the dashboard — the prices in the rate table still belong to the seller. Under Settings › Shipping, the “Refresh Dropp zones” button fetches the lists right away, and the zone form shows when they were last synced. The same refresh can run nightly as a scheduled task (
django_celery_beat), documented indocs/shipping-rate-tables-plan.md; it is set up manually for each environment. If Dropp fails, or returns an empty list, the previous postal codes stay unchanged.Synced Dropp zones now control availability: if a Dropp connection has an active synced zone for home delivery (or Flytjandi), that shipping option is not offered for postal codes outside the zone, regardless of the rate table — the prices still belong to the seller. If there is no synced zone, nothing changes. Renewals that fall outside the zone are still charged the fixed fee, and a warning is logged.
September 14 2026
Shipping rate tables (step one): a shipping option can now have a rate table by zone (
ShippingZone, postal codes and ranges) and weight band (ShippingRate), in the style of Dropp’s price list. Renewals are priced by the contract’s delivery postal code and the calculated weight of the products; if an option has no rate table, the fixed fee still applies and nothing changes. For now, rate tables are set up in the Django admin; a dashboard interface and postal code selection at purchase come in the next steps.Shipping rate tables (step two): the rate table now applies at purchase.
POST /api/v2/checkouts/, checkout sessions, payment pages and embedded Teya/Adyen payments price a shipping option that has a rate table by the postal code of the delivery address and the weight of the products, and reject an option whose rate table does not cover the shipment (shipping_not_available). The checkout session quote request acceptsdelivery_zip_codeand returnsshipping_optionspriced for the shipment; the widget and payment pages fetch the list again when the postal code changes.shipping_selectionrecords thezone_nameandweight_bandthe price was read from.Shipping rate tables (step three): zones and rate tables are now set up in the dashboard instead of the Django admin. Under Settings › Shipping there is a new list of shipping zones where postal codes are entered as ranges and single codes (“101-113, 170, 200-276”); zones synced from a carrier are locked. Each shipping option gets a rate table below the shipping option form — rows are weight bands, columns are zones plus a column for “Everywhere else” — and the table is saved in one go, so if the server rejects one row, the previous table stays unchanged. For Dropp options in ISK, Dropp’s price list (Dropp 2026) can be loaded with one click; it sets up the zones it needs. The catalog now marks products without a weight with “No weight” when any shipping option is priced by a rate table, because such products cannot be shipped with those options.
September 11 2026
The shipping fee is now charged. The fee is part of the quote (
total_amounton/api/v2/checkouts/and theshipping_feebreakdown) and is added as a line of typeshippingto every billing run that ships products — the first billing run that ships and every renewal. Promotion codes and combo discounts do not reduce the fee, and the shipping option’sfree_above_amountthreshold is evaluated against the billing run’s product amount after discounts. Renewals use the shipping option’s current price; if the option has been deleted, the agreed fee is used. The fee follows theshippingfeature, and shipping selections recorded before this release are not charged.Accounting integrations gained
shipping_product_id: the accounting product that shipping fee lines are posted to (its VAT rate must match the fee); the default product is used if it is not set.Shipping options (
shipping-optionsin the dashboard) gainedtax_rate: the VAT rate that applies to the shipping fee, since shipping often carries a different rate than the product. If it is not set, the account’s default tax rate applies.linesin billing run responses (/api/v2/billing-runs/and webhooks) can now contain theline_typevalueshipping.
September 7 2026
New V2 endpoints for creating, fetching, updating and deleting coupons and promotion codes:
/api/v2/coupons/,/api/v2/coupons/{couponId}/,/api/v2/promotion-codes/and/api/v2/promotion-codes/{promotionCodeId}/. Lists support filters (valid,duration,code,coupon,active,customer_referenceand more) andpage_sizepagination. Deletion is a soft delete, and deleting a coupon or code that has already been redeemed is rejected.Expired coupons and promotion codes (
redeem_by/expires_atin the past) can now be updated and deleted, both in the dashboard and through the API; a date in the past is only rejected on a coupon or code that is still valid. Amax_redemptionsvalue of 0 is now stored as no limit.Swagger (
V2 Coupons) and the documentation have been updated; see Coupons and promotion codes.Combo discounts: in the dashboard, a seller can now set a product to get an automatic discount (a percentage or a fixed amount) when the customer also has certain other products — whether they are bought in the same order or are on another active contract. The discount is calculated automatically on every billing run and stops applying when the customer no longer has the qualifying products.
/api/v2/subscription-offer-quotes/,/api/v2/checkouts/andcheckout-sessionsquotes now return thecombo_discountslist with the combo discounts that apply; thesubtotal_amount,tax_amount,total_amountandrecurring_*amounts already include the discount. The offer quote request (subscription-offer-quotes) now accepts an optionalcustomerto take the customer’s other contracts into account, whether or not a promotion code is sent.
August 19 2026
unit_amount_override(a fixed per-unit item price) is now supported in the V2 item operations on an active contract:items/update,items/addandproration-previewon/api/v2/subscription-contracts/{id}/. Previously the field only worked at contract creation. Initems/update, omitting the field keeps the item’s current fixed price, while an explicitnullremoves it so the item reverts to the catalog price. Proration lines resulting from such a change get the newproration_reasonvalueunit_amount_changed.The item operation endpoints (
items/add,items/update,items/remove,proration-previewand related operations) now reject unknown fields, and fields not supported by the selectedoperation, with a400error instead of silently ignoring them. Integrations that sent extra fields to these endpoints need to remove them.items/updatenow only accepts theoperationvalueupdate_item.Swagger and the documentation have been updated accordingly; see Subscription Contracts V2.
January 26 2026
New endpoint /api/subscriptions/{subscriptionId}/set_expiry/ that allows changing the expiry date of a subscription.
December 15 2025
Customers (/api/customers/) now accept and return a phone number (phone) when updated through the API and the Swagger documentation has been updated accordingly.
November 25 2025
New endpoint for transactions so it is now possible to fetch lists of transactions and filter them.
October 9 2025
It is now possible to supply a payment processor id when creating new checkouts. Before, it was only possible to specify a plan to pick a specific payment processor.
Payment processor information is now supplied when fetching plans.
August 29 2025
New API endpoint /api/payments/{uuid}/refund/ that allows refunds for single one-off payments
September 26 2024
New subscription values that indicate whether a subscription has been canceled, cancelled and cancel_date.
Discrepancies in Swagger documentation has been fixed according to responses from the web service.
September 3 2024
Ordering is now possible in the /api/subscriptions endpoint.
April 18 2024
New endpoint /api/webhooks/ which allows users to create and work with web-hooks that can send notifications about events that happen within Áskell.
February 28 2024
New endpoint /api/hello/ that confirms that the web-service works and can be used for testing.
amount and discount can now be used as optional variables when a subscription is added to a customer within /api/customers/{reference}/subscriptions/add/
January 5 2024
Swagger documentation fixed. GET added to individual payments on the URL https://askell.is/api/payments/{uuid}/.
December 7 2023
Users can limit the output that the subscription export delivers by adding the variable
?type=lightto the URL. By doing this less data is extracted about the customer and transaction history and is better when exporting a large list of subscriptions for handling. More data can then be extracted on individual subscriptions if needed.
December 2 2023
New option when fetching a list of subscriptions or customers. You can add the parameter
?page_size=100to the URL to get 100 records at a time. The output then changes from a list of records to a list of records inresults, the number of records incountand links to the next and previous page innextandprevious. The maximum page size is 1000 records.