Factuarea APIDevelopers
Added

Packs and a common storefront for products

Packs get their own API with images and a web view, products can be published to the web with prices with and without VAT, and invoices accept pack lines with the price charged.

Packs and the web storefront are now part of the public contract. They are available on every plan that includes products, from Esencial. Esencial keeps up to 5 packs per account that are not archived; the other plans have no cap.

  • Packs have their own resource: composition, price, availability, images (up to 5, with public and permanent URLs), view=storefront for websites, conditional reads with ETag and a price breakdown by price list, customer (client_id), date and channel.
  • Products share the storefront contract: channels.web, slug, summary, seo, sale_price{net, tax, gross}, availability and image alt, width and height. A bulk operation publishes or withdraws up to 50 products.
  • Document lines accept {pack_id, quantity, sold_on, unit_price, prices_include_tax, print_mode}. A paid web sale is invoiced with the price charged, to the cent, even if the pack was archived later.
  • A pack prints the same way in every document: each product on its own line, labelled with the pack, and the saving under the last one. print_mode only accepts full_breakdown.
  • Product lines with unit_price accept prices_include_tax per line.
  • Webhooks add pack.created, pack.updated, pack.archived, pack.restored, pack.deleted and product.deleted.

Read Packs and Your store with Factuarea.

Events

EventChange
pack.created, pack.updated, pack.archived and pack.restoredNew, with the pack in view=all
pack.deletedNew, with {id, object: "pack", deleted: true}
product.deletedNew, with {id, object: "product", deleted: true}
product.updatedAlso when a product is activated or deactivated, and when its gallery, content, slug, web channel, variants or availability status change

New errors: pack_not_found, slug_already_exists, pack_in_use, pack_composition_too_small, invalid_pack_component, duplicate_pack_component, invalid_pack_pricing, pack_price_unreachable, pack_price_allocation_impossible, invalid_pack_status_transition, pack_not_sellable, pack_image_limit_reached, pack_snapshot_invalid, pack_lines_must_be_expanded, pack_line_locked and pack_print_mode_not_allowed.

Contract up to date

This publication also covers the final contract changes for packs, offers and price lists. The affected operations are in the list below.

  • Packs. sellable.code is a stable, nullable code (archived, inactive, out_of_window, no_channel, component_unsellable or price_unreachable), and null when the pack can be sold. Changing or deleting the images of a pack that belongs to another company answers 404 pack_not_found.
  • Price lists. Updating, deleting or touching the items of a price list from another company answers 404 price_list_not_found. Deleting an item that does not exist answers the new 404 price_list_item_not_found, with param item_id. The domain errors duplicate_price_list_name, invalid_price_list_item, inactive_price_list and price_list_in_use carry their code and their param.
  • Idempotency. The write operations of packs, offers and price lists (19 writes) answer 409 idempotency_key_in_use while another request with the same Idempotency-Key is still running. Retry after a few seconds with the same key and body.
  • Products. A price[gte], price[lte] or similar filter with a non-numeric value answers 400 parameter_invalid_format, with param.
  • Plan cap. On the Esencial plan an account keeps up to 5 packs that are not archived, active or inactive, across its companies. POST /v1/companies/{company}/packs and POST /v1/companies/{company}/packs/{pack}/restore answer 402 plan_limit_exceeded with details.resource packs, current and limit when the account is full, and save nothing. Archive or delete a pack to free a slot, or upgrade the plan. The other plans have no cap.
  • Modules. The v1 packs and promotions resources require the products module on every request and answer 403 feature_not_available_in_plan when it is missing. products and price-lists answer as before. A pack line by pack_id in a document requires the packs module.
  • Offers. The label accepts 24 characters at most.
  • Documents. The line examples include pack_group: null.

New endpoints12

EndpointDescription
GET/v1/companies/{company}/packsList all packs
POST/v1/companies/{company}/packsCreate a pack
GET/v1/companies/{company}/packs/{pack}Retrieve a pack
PATCH/v1/companies/{company}/packs/{pack}Update a pack
DEL/v1/companies/{company}/packs/{pack}Delete a pack
POST/v1/companies/{company}/packs/{pack}/archiveArchive a pack
POST/v1/companies/{company}/packs/{pack}/restoreRestore a pack
GET/v1/companies/{company}/packs/{pack}/price-breakdownGet the price breakdown of a pack
POST/v1/companies/{company}/packs/{pack}/imagesUpload an image to a pack
PATCH/v1/companies/{company}/packs/{pack}/images/{image}Update a pack image
DEL/v1/companies/{company}/packs/{pack}/images/{image}Remove a pack image
POST/v1/companies/{company}/products/bulk-channelsBulk publish or withdraw products on the web

Updated endpoints104

EndpointDescription
POST/v1/companies/{company}/invoices/bulk-createBulk create invoices
POST/v1/accounts/{account}/webhooksCreate an account webhook endpoint
POST/v1/accounts/{account}/api-keysCreate an API key
POST/v1/companies/{company}/invoices/{invoice}/correctiveGenerate corrective invoice
POST/v1/companies/{company}/delivery-notesCreate a delivery note
POST/v1/companies/{company}/invoicesCreate an invoice
POST/v1/companies/{company}/productsCreate a product
GET/v1/companies/{company}/productsList all products
POST/v1/companies/{company}/products/{product}/presentationsCreate a product presentation
GET/v1/companies/{company}/products/{product}/presentationsList product presentations
POST/v1/companies/{company}/products/{product}/variantsCreate a product variant
GET/v1/companies/{company}/products/{product}/variantsList product variants
POST/v1/companies/{company}/proformasCreate a proforma
POST/v1/companies/{company}/quotesCreate a quote
POST/v1/companies/{company}/recurring-invoicesCreate a recurring invoice
POST/v1/companies/{company}/webhook-endpointsCreate a webhook endpoint
GET/v1/companies/{company}/webhook-endpointsList all webhook endpoints
PATCH/v1/accounts/{account}/webhooks/{webhook}Update an account webhook endpoint
PATCH/v1/companies/{company}/delivery-notes/{delivery_note}Update a delivery note
PATCH/v1/companies/{company}/invoices/{invoice}Update an invoice
GET/v1/companies/{company}/products/{product}Retrieve a product
PATCH/v1/companies/{company}/products/{product}Update a product
PATCH/v1/companies/{company}/products/{product}/presentations/{presentation}Update a product presentation
PATCH/v1/companies/{company}/products/{product}/variants/{variant}Update a product variant
POST/v1/companies/{company}/products/{product}/videoUpload a video to a product
PATCH/v1/companies/{company}/proformas/{proforma}Update a proforma
PATCH/v1/companies/{company}/quotes/{quote}Update a quote
PATCH/v1/companies/{company}/recurring-invoices/{recurring_invoice}Update a recurring invoice
GET/v1/companies/{company}/webhook-endpoints/{webhook_endpoint}Retrieve a webhook endpoint
PATCH/v1/companies/{company}/webhook-endpoints/{webhook_endpoint}Update a webhook endpoint
POST/v1/companies/{company}/products/find-by-external-idFind a product by external ID
POST/v1/companies/{company}/products/find-by-skuFind a product by SKU
GET/v1/companies/{company}/products/low-stock-reportList products below the stock threshold
GET/v1/companies/{company}/eventsList all events
GET/v1/companies/{company}/products/{product}/configurationsList product commercial combinations
GET/v1/companies/{company}/webhook-endpoints/{webhook_endpoint}/deliveriesList webhook deliveries
POST/v1/companies/{company}/products/{product}/base-unit-replacementReplace a product by changing its base unit
POST/v1/companies/{company}/products/{product}/resolve-selectionResolve a catalog selection
POST/v1/companies/{company}/webhook-endpoints/{webhook_endpoint}/rotate-secretRotate webhook secret
GET/v1/companies/{company}/products/searchSearch products
POST/v1/accounts/{account}/webhooks/{webhook}/testSend a test event to an account webhook endpoint
POST/v1/companies/{company}/webhook-endpoints/{webhook_endpoint}/test-eventSend a test event
GET/v1/companies/{company}/events/{event}Retrieve an event
GET/v1/companies/{company}/webhook-endpoints/{webhook_endpoint}/deliveries/{delivery}Retrieve webhook delivery
POST/v1/companies/{company}/products/{product}/toggle-activeToggle product active state
PATCH/v1/companies/{company}/products/{product}/stockUpdate product stock
POST/v1/companies/{company}/proformas/{proforma}/acceptAccept a proforma
POST/v1/companies/{company}/quotes/{quote}/acceptAccept a quote
POST/v1/companies/{company}/invoices/{invoice}/annulAnnul an invoice
POST/v1/companies/{company}/invoices/{invoice}/assign-real-numberAssign a real invoice number
POST/v1/companies/{company}/delivery-notes/{delivery_note}/cancelCancel a delivery note
POST/v1/companies/{company}/delivery-notes/{delivery_note}/convertConvert delivery note to invoice
POST/v1/companies/{company}/proformas/{proforma}/convertConvert proforma to invoice
POST/v1/companies/{company}/quotes/{quote}/convertConvert quote to invoice
GET/v1/companies/{company}/delivery-notesList all delivery notes
GET/v1/companies/{company}/invoicesList all invoices
POST/v1/companies/{company}/price-listsCreate a price list
GET/v1/companies/{company}/proformasList all proformas
GET/v1/companies/{company}/quotesList all quotes
POST/v1/companies/{company}/invoices/{invoice}/create-recurringCreate a recurring invoice from an invoice
GET/v1/companies/{company}/delivery-notes/{delivery_note}Retrieve a delivery note
GET/v1/companies/{company}/invoices/{invoice}Retrieve an invoice
DEL/v1/companies/{company}/price-lists/{priceList}Delete a price list
PATCH/v1/companies/{company}/price-lists/{priceList}Update a price list
DEL/v1/companies/{company}/price-lists/{priceList}/items/{item}Delete a price list item
GET/v1/companies/{company}/proformas/{proforma}Retrieve a proforma
GET/v1/companies/{company}/quotes/{quote}Retrieve a quote
POST/v1/companies/{company}/delivery-notes/{delivery_note}/duplicateDuplicate a delivery note
POST/v1/companies/{company}/invoices/{invoice}/duplicateDuplicate an invoice
POST/v1/companies/{company}/proformas/{proforma}/duplicateDuplicate a proforma
POST/v1/companies/{company}/quotes/{quote}/duplicateDuplicate a quote
POST/v1/companies/{company}/delivery-notes/find-by-external-idFind a delivery note by external ID
POST/v1/companies/{company}/invoices/find-by-external-idFind an invoice by external ID
POST/v1/companies/{company}/invoices/find-by-numberFind an invoice by number
POST/v1/companies/{company}/proformas/find-by-external-idFind a proforma by external ID
POST/v1/companies/{company}/quotes/find-by-external-idFind a quote by external ID
POST/v1/companies/{company}/invoices/{invoice}/issueIssue an invoice
GET/v1/companies/{company}/invoices/{invoice}/correctivesList corrective invoices
POST/v1/companies/{company}/price-lists/{priceList}/itemsUpsert a price list item
POST/v1/companies/{company}/delivery-notes/{delivery_note}/mark-deliveredMark delivery note as delivered
POST/v1/companies/{company}/invoices/{invoice}/mark-paidMark invoice as paid
POST/v1/companies/{company}/invoices/{invoice}/mark-sentMark an invoice as sent
POST/v1/companies/{company}/price-lists/{priceList}/items/{item}/purgePermanently delete a retired price list item
POST/v1/companies/{company}/price-lists/{priceList}/items/{item}/reassignReassign a retired price list item
POST/v1/companies/{company}/proformas/{proforma}/rejectReject a proforma
POST/v1/companies/{company}/quotes/{quote}/rejectReject a quote
PATCH/v1/companies/{company}/invoices/{invoice}/rescheduleReschedule an invoice
POST/v1/companies/{company}/invoices/{invoice}/scheduleSchedule an invoice
POST/v1/companies/{company}/invoices/{invoice}/sendSend invoice by email
POST/v1/companies/{company}/proformas/{proforma}/sendSend proforma by email
POST/v1/companies/{company}/quotes/{quote}/sendSend quote by email
POST/v1/companies/{company}/delivery-notes/{delivery_note}/signSign a delivery note
POST/v1/companies/{company}/invoices/substitute-simplifiedSubstitute simplified invoices with full invoice
POST/v1/companies/{company}/invoices/{invoice}/unscheduleUnschedule an invoice
POST/v1/companies/{company}/invoices/{invoice}/unsendUnsend an invoice
POST/v1/companies/{company}/invoices/{invoice}/voidVoid an invoice
GET/v1/companies/{company}/recurring-invoicesList all recurring invoices
GET/v1/companies/{company}/recurring-invoices/{recurring_invoice}Retrieve a recurring invoice
POST/v1/companies/{company}/recurring-invoices/find-by-external-idFind a recurring invoice by external ID
POST/v1/companies/{company}/recurring-invoices/{recurring_invoice}/activateActivate recurring invoice
POST/v1/companies/{company}/recurring-invoices/{recurring_invoice}/pausePause recurring invoice
POST/v1/companies/{company}/recurring-invoices/{recurring_invoice}/resumeResume recurring invoice
POST/v1/companies/{company}/recurring-invoices/{recurring_invoice}/skipSkip the next recurring invoice generation
POST/v1/companies/{company}/recurring-invoices/{recurring_invoice}/cancelCancel recurring invoice

On this page

Need a hand?Contact support