Vendors

1 endpoints
GET /vapi/v1/vendors

List vendors connected to the integrator

Returns every active vendor connection for the integrator. Response envelope: { vendors: [ {...} ] }, each element matching ConnectedVendor. This is the discovery endpoint: unlike every other VAPI endpoint it needs only the integrator token (send the header with an empty vendor half, base64("<integrator_token>:")), and it requires no data_access permission. Each row includes that connection's vendor token. TREAT THE RESPONSE AS CREDENTIAL MATERIAL -- the token values are what authenticate every other endpoint. Not paginated: all active connections are returned in one response.

Example

curl -X GET "https://app.posabit.com/vapi/v1/vendors" \
  -H "Authorization: Basic BASE64(INTEGRATOR_TOKEN:VENDOR_TOKEN)" \
  -H "Accept: application/json"

Responses

Status Description
200 Success
401 Invalid or inactive integrator token

Response Fields

Field Type Required Description
status string(20) No Default: active
name string Yes
description text No
address string No
city string No
state string(2) No
zip string(10) No
phone string No
email string No
website string No
contact_name string No
created_at datetime Yes
updated_at datetime Yes
logo string No
timezone string No
suppliers_count integer No Default: 0
core_brands_count integer No Default: 0
is_supplier boolean No Default: false
has_catalogs boolean No Default: false
inheritor_id integer No
territory string(2) No
region_id integer No
merged boolean No Default: false
core_isn string No
core_token string No
retailers_count integer No Default: 0
retailers_analyzed_at datetime No
subscription_id integer No
subscription_price integer No
salesforce_account_number string No
last_subscription_changed datetime No
is_demo boolean Yes Default: false
last_rate_card_changed_at datetime No
enable_catalog boolean No Default: false
freemium boolean Yes Default: false
freemium_trial_expires_at date No
distributor_access boolean Yes Default: false
catalog_swept_at datetime No

Models

ConnectedVendorListResponse

All active vendor connections for the authenticated integrator.

Property Type Required Description
vendors array (ConnectedVendor) Yes Connected vendors
ConnectedVendor

A vendor the integrator is connected to, plus the token authorizing that connection.

Property Type Required Description
id integer Yes Vendor id (pass as the vendor_id query param on other endpoints)
name string No Vendor name
status string No Vendor account status
email string No Contact email
phone string No Contact phone
contact_name string No Primary contact name
address string No Street address
city string No City
state string No State
zip string No Postal code
website string No Website URL
description string No Vendor description
logo string No Logo URL. NULL when no logo is attached
territory string No Sales territory
timezone string No Vendor's local timezone (the zone the sales share report's dates are interpreted in)
retailers_count integer No Number of retailers linked to the vendor
suppliers_count integer No Number of suppliers linked to the vendor
token string Yes CREDENTIAL. This connection's vendor token -- the vendor half of the Basic auth header on every other endpoint

Inventories

1 endpoints
GET /vapi/v1/retailers/{retailer_id}/inventories

Get VMI inventory data for a retailer

Returns the vendor's inventory position at one retailer, computed from the nightly warehouse rollup. Response envelope: { meta: {...}, inventory: [ {...} ] }. Each element matches `meta.venue_license_number` is the venue's STS license number — the recommended key for matching venues across systems. VendorInventoryItem; meta matches VendorInventoryMeta. Rows are ordered by the retailer SKU's updated_at, most recently touched first. The underlying rollup is capped at 3000 SKUs per retailer, so a vendor above that ceiling loses its stalest SKUs rather than an arbitrary slice. RECOMMENDED: pass exclude_inactive=true. Most integrations want the SKUs the retailer actually carries, and that is what this returns -- dropping archived SKUs, SKUs the retailer deactivated, and SKUs with no inventory activity in 90 days. It applies the same definition as the "Inactive" filter in the vendor portal, so the API and the portal agree on what is live. The default is false only because it predates the filter and changing it would alter existing integrations without warning. Left off, the response also includes SKUs the retailer stopped carrying long ago, which still carry a genuine quantity_on_hand and cost -- expect a materially larger payload and a lower-quality one. Every row carries the three fields the filter decides on, so a client that leaves it off can still classify each SKU itself. A SKU is inactive when ANY of the following holds: archived == true sku_is_active == false updated_at older than 90 days, or absent Use exclude_inactive=false when you specifically want the full historical set -- reconciling against a catalog the retailer has since pruned, or applying your own staleness window to updated_at instead of the 90 days used here. Supports incremental sync via q[updated_at_gt], which matches inventory_skus.updated_at -- the retailer SKU's stock position. Receiving, selling, or adjusting a SKU advances it. IMPORTANT: unlike the other VAPI collections, the rows here are computed, not stored, so this filter is narrower than "everything that changed since :gt". The window-derived fields (velocity, days_supply, weeks_of_supply, pct_days_in_stock, and the sold_* totals) are recalculated against a window that ends today, so they move as the window slides even when the SKU itself was untouched. An integrator that needs those figures current has to re-pull the collection on its own schedule; polling with q[updated_at_gt] alone will not surface that drift. Requires the inventories_access permission on the integrator/vendor connection. A connection without it receives 401 "No permission". RATE LIMIT: 10 requests per minute per integrator token, counted against this endpoint separately from the sales endpoint. Exceeding it returns 429 with { "error": "Rate limit exceeded" } and a Retry-After: 60 header. Note that the 429 body uses an "error" key, while every other VAPI error uses "message". Money fields are integer CENTS unless the field description says otherwise. Quantities are decimals.

Parameters

Name Type In Required Description
retailer_id integer path Yes Retailer ID
vendor_id integer query No Vendor ID (alternative to supplying vendor_token in the auth header)
sales_range_in_weeks integer query No Sales lookback in weeks (default 4)
q[updated_at_gt] datestring query No Only SKUs whose stock position changed after this timestamp (ISO 8601, e.g. 2026-01-01 or 2026-01-01T00:00:00Z). Matches inventory_skus.updated_at
exclude_inactive boolean query No RECOMMENDED: set to true. Drops SKUs the retailer has stopped carrying -- archived SKUs, SKUs the retailer deactivated, and SKUs with no inventory activity in the last 90 days -- leaving what the retailer actually stocks. Defaults to false for backward compatibility, which returns long-dead SKUs indistinguishable from live ones
page integer query No Page number (default 1)
per_page integer query No Results per page (default 100, max 1000; larger values are clamped, not rejected)

Example

curl -X GET "https://app.posabit.com/vapi/v1/retailers/{retailer_id}/inventories" \
  -H "Authorization: Basic BASE64(INTEGRATOR_TOKEN:VENDOR_TOKEN)" \
  -H "Accept: application/json"

Responses

Status Description
200 Success
401 Invalid integrator token, invalid vendor, or missing inventories_access permission
404 Retailer not found, or not accessible to this vendor
422 Invalid updated_at filter, or exclude_inactive was not a boolean
429 Rate limit exceeded (10/minute per integrator token)

Response Fields

Field Type Required Description
product_id integer Yes
tier_id integer No
barcode string No
price integer Yes Default: 0
last_price integer No
cost integer Yes Default: 0
discountable boolean Yes Default: true
quantity_on_hand decimal Yes Default: 0.0
optimum_level integer No Default: 0
reorder_threshold integer No
calc_threshold integer No
last_replenish_date datetime No
velocity decimal Yes Default: 0.0
sold integer Yes Default: 0
days_supply integer Yes Default: 0
avg_cost integer No
avg_price integer No
sync_expires_at datetime No
last_order datetime No
created_at datetime No
updated_at datetime No
supplier_id integer No
updated_by string No
unit string(15) Yes Default: units
weight decimal Yes Default: 0.0
weight_unit string(15) No
is_active boolean No Default: true
notes text No
sellable_quantity decimal Yes Default: 0.0
ecomm_quantity decimal Yes Default: 0.0
allow_undercost boolean Yes Default: false
manifest_items_count integer No Default: 0
thc decimal No
cbd decimal No
cbn decimal No
equivalent_weight decimal No
equivalent_unit string No
thc_min decimal No
thc_max decimal No
cbd_min decimal No
cbd_max decimal No
cbn_min decimal No
cbn_max decimal No
api_id string No
inheritor_id integer No
med_price integer No
terpenes text No
manifest_transfer_date date No
thca decimal No
thca_min decimal No
thca_max decimal No
cbda decimal No
cbda_min decimal No
cbda_max decimal No
total_thc decimal No
total_thc_min decimal No
total_thc_max decimal No
producer_id integer No
doh_compliant boolean No Default: false
total_cbd decimal No
total_cbd_min decimal No
total_cbd_max decimal No
last_received_quantity decimal No Default: 0.0

Models

PaginationMeta

Pagination state for the enclosing collection.

Property Type Required Description
page integer Yes Current page number (1-based)
per_page integer Yes Rows per page
total integer Yes Total rows matching the request across all pages
total_pages integer Yes Total number of pages
max_per_page integer Yes Ceiling on per_page. A larger requested value is clamped to this rather than rejected
InventoryListResponse

Paginated VMI inventory rows for one retailer.

Property Type Required Description
meta VendorInventoryMeta Yes Pagination state plus the report window and retailer identity
inventory array (VendorInventoryItem) Yes Inventory rows
VendorInventoryMeta

Pagination state plus the window and retailer the rows were computed for.

Property Type Required Description
page integer Yes Current page number (1-based)
per_page integer Yes Rows per page
total integer Yes Total rows matching the request across all pages
total_pages integer Yes Total number of pages
max_per_page integer Yes Ceiling on per_page. A larger requested value is clamped to this rather than rejected
sales_range_in_weeks integer Yes Sales lookback applied to velocity and sold_* fields
period_start string Yes First day of the sales window (ISO 8601 date)
period_end string Yes Last day of the sales window (ISO 8601 date)
retailer_name string No Retailer name
venue_name string No Venue name (null if the retailer has no linked venue)
VendorInventoryItem

One of the vendor's SKUs at the retailer, with stock position and sell-through over the requested window.

Property Type Required Description
core_product_id integer No Vendor catalog product id (matches id from the products endpoint)
sku_reference string No Retailer's SKU barcode
sku_id integer No Retailer's inventory SKU id
core_product_name string No Product name in the vendor's catalog
retailer_product_name string No Product name as the retailer has it
product_type_name string No Product type / category name
product_type_color string No Product type display color (hex)
brand_name string No Brand name
strain_name string No Strain name
lineage string No Strain lineage (e.g. indica, sativa, hybrid)
quantity_on_hand float No Units on hand at the retailer
sellable_quantity float No Units available to sell
cost float No Cost in CENTS, from the vendor catalog
sku_cost float No Cost in CENTS the retailer recorded for this SKU
velocity float No Average units sold per day over the sales window
days_supply float No Days of stock remaining at current velocity. NULL when velocity is zero (supply is unbounded)
weeks_of_supply float No days_supply / 7, rounded to 1 decimal. NULL when days_supply is null
pct_days_in_stock float No Percentage of days in the window the SKU had stock on hand (0-100)
avg_retail_price_per_unit float No Average retail price per unit sold, in CENTS. 0.0 when nothing sold
min_reorder_qty integer No Minimum reorder quantity from the vendor catalog
optimum_level integer No Retailer's target stock level
reorder_threshold integer No Retailer's reorder trigger level
last_received_date datetime No When the retailer last received this SKU
last_received_quantity float No Units received on that last receipt
last_order_at datetime No When this SKU last sold
units_sold float No Units sold during the sales window
sold_cost_amount float No Cost of goods sold during the window, in CENTS
sold_price_amount float No Gross retail sales during the window, in CENTS
sold_discount_amount float No Discounts applied during the window, in CENTS
updated_at datetime No When the retailer's SKU last changed (UTC, ISO 8601) -- receiving, selling, or adjusting it advances this. Feed the value back as q[updated_at_gt] to poll forward. Does NOT move when only the window-derived metrics change
sku_is_active boolean No False once the retailer stops ordering this SKU
archived boolean No True once the retailer archives the underlying product

Sales

1 endpoints
GET /vapi/v1/retailers/{retailer_id}/sales

Get sales data for a retailer

Returns the vendor's daily sales at one retailer, aggregated by product type. Response envelope: { meta: {...}, sales: [ {...} ] }. Each element matches VendorSalesRow; meta matches PaginationMeta. Accepts a custom date range via start_date/end_date (ISO 8601, e.g. 2025-01-01). The range must not exceed 31 days and defaults to the last 30 days. Dates are interpreted in the RETAILER VENUE's local timezone (falling back to America/Los_Angeles), not UTC and not the vendor's timezone. Days with no sales are returned as zero-filled rows rather than omitted, so the row count is (days in range x product types), not the number of days that had sales. Requires the sales_access permission on the integrator/vendor connection. A connection without it receives 401 "No permission". RATE LIMIT: 10 requests per minute per integrator token, counted against this endpoint separately from the inventories endpoint. Exceeding it returns 429 with { "error": "Rate limit exceeded" } and a Retry-After: 60 header. Note that the 429 body uses an "error" key, while every other VAPI error uses "message". Money fields are integer CENTS.

Parameters

Name Type In Required Description
retailer_id integer path Yes Retailer ID
vendor_id integer query No Vendor ID (alternative to supplying vendor_token in the auth header)
start_date string query No Start date (ISO 8601, e.g. 2025-01-01). Required if end_date is given
end_date string query No End date (ISO 8601, e.g. 2025-01-31). Required if start_date is given
page integer query No Page number (default 1)
per_page integer query No Results per page (default 100, max 1000; larger values are clamped, not rejected)

Example

curl -X GET "https://app.posabit.com/vapi/v1/retailers/{retailer_id}/sales" \
  -H "Authorization: Basic BASE64(INTEGRATOR_TOKEN:VENDOR_TOKEN)" \
  -H "Accept: application/json"

Responses

Status Description
200 Success
401 Invalid integrator token, invalid vendor, or missing sales_access permission
404 Retailer not found, or not accessible to this vendor
422 Invalid or out-of-range dates
429 Rate limit exceeded (10/minute per integrator token)

Models

SalesListResponse

Paginated daily sales rows for one retailer.

Property Type Required Description
meta PaginationMeta Yes Pagination state
sales array (VendorSalesRow) Yes Sales rows
VendorSalesRow

The vendor's sales at this retailer for one day and one product type. Zero-filled when there were no sales that day.

Property Type Required Description
order_date string Yes Day of the sale (ISO 8601 date, in the retailer venue's timezone)
iso_week integer No ISO week number of order_date
iso_year integer No ISO year of order_date
product_type_name string No Product type / category name
product_type_color string No Product type display color (hex)
total_quantity float No Units sold
total_price float No Gross retail sales in CENTS
total_profit float No Retailer margin in CENTS (price less credits, discounts and cost)
total_cost float No Cost of goods sold in CENTS

Customer Sales

1 endpoints
GET /vapi/v1/retailers/{retailer_id}/customer_sales

Get item-level sales with customer demographics for a retailer

Returns one row per sold line item from Redshift, each with the anonymized customer demographics shown on the monthly vendor Sales Export. Accepts a custom date range via start_date/end_date (ISO 8601, e.g. 2026-01-01). The range must not exceed 31 days. Defaults to the last 30 days. customer.id is an HMAC digest scoped to the authenticated vendor: stable across this vendor's rows, but not reversible and not comparable against any other feed. Full date of birth is never returned -- birth_year and the age at time of order are. Money values are USD dollars. Only settled orders (COMPLETE, DELIVERED) are included, so counts will not tie out exactly against the monthly CSV export.

Parameters

Name Type In Required Description
retailer_id integer path Yes Retailer ID
start_date string query No Start date (ISO 8601, e.g. 2026-01-01)
end_date string query No End date (ISO 8601, e.g. 2026-01-31)
page integer query No Page number (default 1)
per_page integer query No Results per page (default 100, max 1000)

Example

curl -X GET "https://app.posabit.com/vapi/v1/retailers/{retailer_id}/customer_sales" \
  -H "Authorization: Basic BASE64(INTEGRATOR_TOKEN:VENDOR_TOKEN)" \
  -H "Accept: application/json"

Responses

Status Description
200 Success
401 Unauthorized
404 Not Found
422 Invalid or out-of-range dates

Products

1 endpoints
GET /vapi/v1/retailers/{retailer_id}/products

Get core products carried by a retailer

Returns the vendor's catalog products that this retailer currently stocks on at least one active SKU. Response envelope: { products: [ {...} ], meta: {...} }. Each element matches VendorCatalogProduct; meta matches PaginationMeta. Supports incremental sync via q[updated_at_gt]. The filter matches a change to either the catalog product or the retailer's stocking of it, so a product the retailer began carrying since the last poll is returned even though the catalog record itself did not change. Requires the products_access permission on the integrator/vendor connection. A connection without it receives 401 "No permission". The brand, strain and product_type keys are OMITTED entirely (not null) when the product has no such association. Money fields are integer CENTS.

Parameters

Name Type In Required Description
retailer_id integer path Yes Retailer ID
vendor_id integer query No Vendor ID (alternative to supplying vendor_token in the auth header)
q[updated_at_gt] datestring query No Only products whose catalog record or retailer SKU was updated after this timestamp (ISO 8601, e.g. 2026-01-01 or 2026-01-01T00:00:00Z)
page integer query No Page number (default 1)
per_page integer query No Results per page (default 100, max 1000; larger values are clamped, not rejected)

Example

curl -X GET "https://app.posabit.com/vapi/v1/retailers/{retailer_id}/products" \
  -H "Authorization: Basic BASE64(INTEGRATOR_TOKEN:VENDOR_TOKEN)" \
  -H "Accept: application/json"

Responses

Status Description
200 Success
401 Invalid integrator token, invalid vendor, or missing products_access permission
404 Retailer not found, or not accessible to this vendor
422 Invalid updated_at filter

Response Fields

Field Type Required Description
monetary_value integer No Default: 0
name string No
display_name string No
image string No
product_type_id integer No
product_brand_id integer No
product_strain_id integer No
flower_type string No
shared boolean Yes Default: false
created_at datetime No
updated_at datetime No
description string(8000) No Default:
description_html text No
report_cat string No Default:
weight_unit string(2) No
is_sample boolean Yes Default: false
is_medical_only boolean Yes Default: false
weight decimal No Default: 0.0
concentrate_type string No
available_on string Yes Default: everywhere
inheritor_id integer No
skus_count integer No Default: 0
sellable_quantity decimal Yes Default: 0.0
quantity_on_hand decimal Yes Default: 0.0
unit string Yes Default: units
external_id string No
archived boolean Yes Default: false
internal_id string No
curated_product_id integer No
instructions text No
servings integer No
pack_size integer No
tag_list text No
manufacturing_method text No
ingredients text No
solvent string No
allergens text No
thc_per_serving decimal No
cbd_per_serving decimal No
core_product_id integer No
image_assocs_count integer No Default: 0
has_image boolean No Default: false
seo_title string No
seo_meta_description text No
seo_keywords text No
last_catalog_sync datetime No
catalog_synced boolean No Default: false
tag_list_enh text No
ndc_number string No
is_recreational_only boolean Yes Default: false
synced_catalog_fields json No

Models

ProductListResponse

Paginated catalog products the retailer stocks.

Property Type Required Description
products array (VendorCatalogProduct) Yes Catalog products
meta PaginationMeta Yes Pagination state
VendorCatalogProduct

A product in the vendor's catalog that this retailer stocks.

Property Type Required Description
id integer Yes Catalog product id (the core_product_id referenced by the inventories, manifests and purchase order endpoints)
name string No Product name
description string No Product description
weight float No Unit weight, in weight_unit
weight_unit string No Unit for weight (e.g. "gm")
cost integer No Wholesale cost in CENTS
min_reorder_qty integer No Minimum reorder quantity
active boolean No Whether the product is active in the vendor's catalog
brand VendorCatalogRef No Brand. KEY OMITTED when the product has no brand
strain VendorCatalogRef No Strain. KEY OMITTED when the product has no strain
product_type VendorCatalogRef No Product type. KEY OMITTED when the product has no type
thc float No THC value from the catalog record
cbd float No CBD value from the catalog record
created_at datetime No When the catalog record was created (UTC, ISO 8601)
updated_at datetime No When the catalog record was last changed (UTC, ISO 8601). Does NOT move when only the retailer's SKU changes -- use the q[updated_at_gt] filter, which covers both
VendorCatalogRef

An id/name reference to a catalog association.

Property Type Required Description
id integer Yes Record id
name string No Display name

Purchase Orders

1 endpoints
Purchase Orders allow vendors to manage and track orders from their retailers. View all incoming purchase orders, update their status, and communicate directly with retailers through the POSaBIT portal.
GET /vapi/v1/retailers/{retailer_id}/purchase_orders

Get purchase orders for a retailer

Returns purchase orders the retailer has raised against this vendor, newest first. Response envelope: { purchase_orders: [ {...} ], meta: {...} }. Each element matches VendorPurchaseOrder; meta matches PaginationMeta. Supports incremental sync via q[updated_at_gt] / q[updated_at_lt]. Note that purchase_orders.updated_at tracks the order header (state, totals, ref_number); an edit confined to a line item does not advance it. Requires the purchase_orders_access permission on the integrator/vendor connection. A connection without it receives 401 "No permission". Money fields are integer CENTS.

Parameters

Name Type In Required Description
retailer_id integer path Yes Retailer ID
vendor_id integer query No Vendor ID (alternative to supplying vendor_token in the auth header)
q[updated_at_gt] datestring query No Only purchase orders updated after this timestamp (ISO 8601, e.g. 2026-01-01 or 2026-01-01T00:00:00Z)
q[updated_at_lt] datestring query No Only purchase orders updated before this timestamp (ISO 8601)
page integer query No Page number (default 1)
per_page integer query No Results per page (default 100, max 1000; larger values are clamped, not rejected)

Example

curl -X GET "https://app.posabit.com/vapi/v1/retailers/{retailer_id}/purchase_orders" \
  -H "Authorization: Basic BASE64(INTEGRATOR_TOKEN:VENDOR_TOKEN)" \
  -H "Accept: application/json"

Responses

Status Description
200 Success
401 Invalid integrator token, invalid vendor, or missing purchase_orders_access permission
404 Retailer not found, or not accessible to this vendor
422 Invalid updated_at filter

Response Fields

Field Type Required Description
retailer_id integer Yes
created_by integer Yes
manifest_id integer No
aasm_state string Yes Default: draft
created_at datetime Yes
updated_at datetime Yes
items_count integer Yes Default: 0
ref_number string No
owner_type string No
owner_id integer No
total_units integer Yes Default: 0
total_cents integer Yes Default: 0
locked_by_user_id integer No
locked_at datetime No
lock_version integer Yes Default: 0
state_history json No

Models

PurchaseOrderListResponse

Paginated purchase orders for one retailer, newest first.

Property Type Required Description
purchase_orders array (VendorPurchaseOrder) Yes Purchase orders
meta PaginationMeta Yes Pagination state
VendorPurchaseOrder

A purchase order the retailer raised against this vendor.

Property Type Required Description
id integer Yes Purchase order id
ref_number string No Retailer-facing reference number
state string No Workflow state (e.g. draft, submitted, accepted)
items_count integer No Number of line items
created_at datetime No When the order was created (UTC, ISO 8601). Results are ordered by this field, descending
updated_at datetime No When the order header last changed (UTC, ISO 8601). Line-item-only edits do not advance it
items array (VendorPurchaseOrderItem) No Line items
VendorPurchaseOrderItem

One line item on a purchase order.

Property Type Required Description
id integer Yes Line item id
core_product_id integer No Vendor catalog product id (matches id from the products endpoint)
quantity integer No Units ordered
cost integer No Unit cost in CENTS

Manifests

2 endpoints
GET /vapi/v1/retailers/{retailer_id}/manifests

Get manifests for a retailer

Returns the vendor's inbound transfer manifests to this retailer, newest first. Response envelope: { manifests: [ {...} ], meta: {...} }. Each element matches VendorManifestSummary; meta matches PaginationMeta. Accepted manifests with a zero accepted_cost are treated as samples and excluded from this collection. Supports incremental sync via q[updated_at_gt] / q[updated_at_lt]. manifests.updated_at advances on the changes an integrator cares about (acceptance, state, costs, transfer date); a manifest_item saved on its own does not touch the header, so poll #show for line-item detail. Requires the manifests_access permission on the integrator/vendor connection. A connection without it receives 401 "No permission". Money fields are integer CENTS.

Parameters

Name Type In Required Description
retailer_id integer path Yes Retailer ID
vendor_id integer query No Vendor ID (alternative to supplying vendor_token in the auth header)
q[updated_at_gt] datestring query No Only manifests updated after this timestamp (ISO 8601, e.g. 2026-01-01 or 2026-01-01T00:00:00Z)
q[updated_at_lt] datestring query No Only manifests updated before this timestamp (ISO 8601)
page integer query No Page number (default 1)
per_page integer query No Results per page (default 100, max 1000; larger values are clamped, not rejected)

Example

curl -X GET "https://app.posabit.com/vapi/v1/retailers/{retailer_id}/manifests" \
  -H "Authorization: Basic BASE64(INTEGRATOR_TOKEN:VENDOR_TOKEN)" \
  -H "Accept: application/json"

Responses

Status Description
200 Success
401 Invalid integrator token, invalid vendor, or missing manifests_access permission
404 Retailer not found, or not accessible to this vendor
422 Invalid updated_at filter

Response Fields

Field Type Required Description
supplier_id integer No
reference_no string No
aasm_state string No Default: pending
transfer_date date No
delivery_time datetime No
notes text No
created_at datetime No
updated_at datetime No
api_id string No
accepted_by string No
accepted_at datetime No
pickup_time datetime No
transportation_type string No
destination_id integer No
driver_name string No
driver_id string No
driver_dob date No
vehicle_id string No
vehicle_year string No
vehicle_color string No
vehicle_model string No
vehicle_make string No
license_plate string No
courier_id integer No
type string No
route text No
courier_license_number string No
voided_lot_numbers text No
transferred_at datetime No
voided_at datetime No
incoming_created_at datetime No
estimated_departed_at datetime No
estimated_arrival_at datetime No
venue_destination_id integer No
received_cost integer No
accepted_cost integer No Default: 0
received_quantity integer No
accepted_quantity integer No Default: 0
has_marijuana boolean Yes Default: false
json_filename string No
import_source string No
discount integer No
excise_tax boolean Yes Default: false
total_excise_tax integer No Default: 0
external_driver_id string No
external_vehicle_id string No
sts_license_id integer No
payment_method string(25) No
core_external_ref string(50) No Default:
external_pdf string No
GET /vapi/v1/retailers/{retailer_id}/manifests/{id}

Get manifest details with line items

Returns one manifest with its line items. Response envelope: { manifest: {...} }, matching VendorManifestDetail. Use this action rather than #index to observe line-item changes, which do not advance the manifest header's updated_at. Requires the manifests_access permission on the integrator/vendor connection. A connection without it receives 401 "No permission". Money fields are integer CENTS.

Parameters

Name Type In Required Description
retailer_id integer path Yes Retailer ID
id integer path Yes Manifest ID
vendor_id integer query No Vendor ID (alternative to supplying vendor_token in the auth header)

Example

curl -X GET "https://app.posabit.com/vapi/v1/retailers/{retailer_id}/manifests/{id}" \
  -H "Authorization: Basic BASE64(INTEGRATOR_TOKEN:VENDOR_TOKEN)" \
  -H "Accept: application/json"

Responses

Status Description
200 Success
401 Invalid integrator token, invalid vendor, or missing manifests_access permission
404 Manifest or retailer not found, or not accessible to this vendor

Response Fields

Field Type Required Description
supplier_id integer No
reference_no string No
aasm_state string No Default: pending
transfer_date date No
delivery_time datetime No
notes text No
created_at datetime No
updated_at datetime No
api_id string No
accepted_by string No
accepted_at datetime No
pickup_time datetime No
transportation_type string No
destination_id integer No
driver_name string No
driver_id string No
driver_dob date No
vehicle_id string No
vehicle_year string No
vehicle_color string No
vehicle_model string No
vehicle_make string No
license_plate string No
courier_id integer No
type string No
route text No
courier_license_number string No
voided_lot_numbers text No
transferred_at datetime No
voided_at datetime No
incoming_created_at datetime No
estimated_departed_at datetime No
estimated_arrival_at datetime No
venue_destination_id integer No
received_cost integer No
accepted_cost integer No Default: 0
received_quantity integer No
accepted_quantity integer No Default: 0
has_marijuana boolean Yes Default: false
json_filename string No
import_source string No
discount integer No
excise_tax boolean Yes Default: false
total_excise_tax integer No Default: 0
external_driver_id string No
external_vehicle_id string No
sts_license_id integer No
payment_method string(25) No
core_external_ref string(50) No Default:
external_pdf string No

Models

ManifestListResponse

Paginated manifests for one retailer, newest first.

Property Type Required Description
manifests array (VendorManifestSummary) Yes Manifests
meta PaginationMeta Yes Pagination state
ManifestDetailResponse

A single manifest with its line items.

Property Type Required Description
manifest VendorManifestDetail Yes The manifest
VendorManifestSummary

A transfer manifest from this vendor to the retailer, as returned by the index action.

Property Type Required Description
id integer Yes Manifest id
reference_no string No Manifest reference number
state string No Workflow state (e.g. pending, incoming, accepted)
transfer_date string No Date of transfer (ISO 8601 date)
delivery_time datetime No Scheduled delivery time
accepted_at datetime No When the retailer accepted the manifest. NULL until accepted
accepted_quantity float No Units the retailer accepted
accepted_cost integer No Accepted value in CENTS
supplier_name string No Supplier name. NULL if the manifest has no linked supplier
supplier_license string No Supplier license number. NULL if the manifest has no linked supplier
created_at datetime No When the manifest was created (UTC, ISO 8601). Results are ordered by this field, descending
updated_at datetime No When the manifest header last changed (UTC, ISO 8601). Line-item-only edits do not advance it
VendorManifestDetail

A transfer manifest with full receiving detail and line items.

Property Type Required Description
id integer Yes Manifest id
reference_no string No Manifest reference number
state string No Workflow state (e.g. pending, incoming, accepted)
transfer_date string No Date of transfer (ISO 8601 date)
delivery_time datetime No Scheduled delivery time
pickup_time datetime No Scheduled pickup time
accepted_at datetime No When the retailer accepted the manifest. NULL until accepted
accepted_by string No Who accepted the manifest
accepted_quantity float No Units the retailer accepted
accepted_cost integer No Accepted value in CENTS
received_quantity float No Units received
received_cost integer No Received value in CENTS
discount integer No Discount applied in CENTS
notes string No Free-text notes
supplier_name string No Supplier name. NULL if the manifest has no linked supplier
supplier_license string No Supplier license number. NULL if the manifest has no linked supplier
driver_name string No Transport driver name
license_plate string No Transport vehicle license plate
vehicle_make string No Transport vehicle make
vehicle_model string No Transport vehicle model
created_at datetime No When the manifest was created (UTC, ISO 8601)
updated_at datetime No When the manifest header last changed (UTC, ISO 8601)
items array (VendorManifestItem) No Line items
VendorManifestItem

One line item on a manifest.

Property Type Required Description
id integer Yes Line item id
name string No Product name as it appears on the manifest
barcode string No Retailer SKU barcode. NULL if the item is not linked to an inventory SKU
quantity float No Units on the manifest
received_quantity float No Units received
cost integer No Unit cost in CENTS
lot_number string No Lot / batch number
expires_on string No Expiry date (ISO 8601 date)
core_product_id integer No Vendor catalog product id (matches id from the products endpoint). NULL if the item is not linked through to a catalog product

Retailers

2 endpoints
GET /vapi/v1/retailers

List all active retailers for the vendor

Returns every retailer the vendor has active, access-granted, live-venue access to. Response envelope: { meta: {...}, retailers: [ {...} ] }, each retailer element matching VendorRetailerSummary. The id returned here is the retailer_id path segment for the inventories, sales, products, purchase orders and manifests endpoints, and the value accepted by the sales share report's retailer_ids filter. `name` is the venue's name and `license_number` is the venue's STS license number, the recommended key for matching venues across systems. Requires the retailers_access permission on the integrator/vendor connection. A connection without it receives 401 "No permission". Not paginated: all accessible retailers are returned in one response, sorted by name (case-insensitive). meta.total is the number of rows in this response. meta.total_connections counts every retailer connection on record for the vendor, including any currently hidden because the retailer is inactive, retailer access is off, or the venue is inactive. A gap between the two means access was withdrawn, not that the connection was deleted.

Parameters

Name Type In Required Description
vendor_id integer query No Vendor ID (alternative to supplying vendor_token in the auth header)

Example

curl -X GET "https://app.posabit.com/vapi/v1/retailers" \
  -H "Authorization: Basic BASE64(INTEGRATOR_TOKEN:VENDOR_TOKEN)" \
  -H "Accept: application/json"

Responses

Status Description
200 Success
401 Invalid integrator token, invalid vendor, or missing retailers_access permission
GET /vapi/v1/retailers/{id}

Get retailer details with inventory metrics

Returns one retailer with a snapshot of the vendor's inventory position there. Response envelope: { retailer: {...} }, matching VendorRetailerDetail. `name` mirrors the venue's name; `venue.license_number` is the venue's STS license number — the recommended key for matching venues across systems. The metrics object is computed on demand. When no metrics are available for the pairing, every metric is returned as NULL rather than the object being omitted or zero-filled. Requires the retailers_access permission on the integrator/vendor connection. A connection without it receives 401 "No permission". Money fields are integer CENTS.

Parameters

Name Type In Required Description
id integer path Yes Retailer ID
vendor_id integer query No Vendor ID (alternative to supplying vendor_token in the auth header)

Example

curl -X GET "https://app.posabit.com/vapi/v1/retailers/{id}" \
  -H "Authorization: Basic BASE64(INTEGRATOR_TOKEN:VENDOR_TOKEN)" \
  -H "Accept: application/json"

Responses

Status Description
200 Success
401 Invalid integrator token, invalid vendor, or missing retailers_access permission
404 Retailer not found, inactive, or not accessible to this vendor

Models

RetailerListResponse

All retailers the vendor can access.

Property Type Required Description
meta RetailerListMeta Yes Row and connection totals
retailers array (VendorRetailerSummary) Yes Retailers
RetailerListMeta

Totals for the list. A gap between them means access was withdrawn, not deleted.

Property Type Required Description
total integer Yes Retailers in this response
total_connections integer Yes Every retailer connection on record for the vendor, visible or not
VendorRetailerSummary

A retailer the vendor has access to.

Property Type Required Description
id integer Yes Retailer id -- the retailer_id path segment used by the other endpoints
name string No Retailer name -- the venue's name
venue_id integer No Underlying POSaBIT venue id
license_number string No Venue STS license number -- the recommended cross-system match key
RetailerDetailResponse

A single retailer with the vendor's inventory metrics there.

Property Type Required Description
retailer VendorRetailerDetail Yes The retailer
VendorRetailerDetail

A retailer with the vendor's current inventory position.

Property Type Required Description
id integer Yes Retailer id
name string No Retailer name
active boolean No Whether the vendor/retailer link is active
venue_id integer No Underlying POSaBIT venue id
venue VendorRetailerVenue No Venue reference. KEY OMITTED when the retailer has no linked venue
metrics RetailerInventoryMetrics Yes Inventory metrics. All members are NULL when no metrics are available
VendorRetailerVenue

The POSaBIT venue behind the retailer.

Property Type Required Description
id integer Yes Venue id
name string No Venue name
RetailerInventoryMetrics

Snapshot of the vendor's inventory position at the retailer. Every member is NULL when no metrics are available for the pairing.

Property Type Required Description
active_lot_count integer No Lots currently in stock
samples_count integer No Sample lots received
samples_on_hand float No Sample units still on hand
skus_count integer No Distinct SKUs of the vendor's the retailer carries
inventory_value integer No Value of the vendor's inventory at the retailer, in CENTS
unmapped_products integer No Retailer products not linked to a vendor catalog product
active_lots integer No Lots with stock on hand
pending_lots integer No Lots on manifests not yet accepted
aged_lots integer No Lots held beyond the aging threshold
recent_products integer No Products first stocked recently

Reports

1 endpoints
Vendor-level reports aggregate across all of your connected retailers rather than a single store, so they are not nested under a retailer id. They read from a nightly rollup, which means figures are complete through yesterday. Money values are USD dollars and share values are 0-1 ratios; format them as percentages client-side. Heavier sections are opt-in through the include parameter, so the default response stays small: you get the totals plus one row per retailer, each with a single blended share. To get a breakdown by product family, pass include=families — for example GET /vapi/v1/reports/sales_share_by_retailer?start_date=2026-05-01&end_date=2026-06-30&include=families — which adds a families array to every retailer row, one entry per product family (Flower, Preroll, Concentrate, …) carrying that family's vendor_cog and its share of the retailer's sales in that family. A null share means the retailer had no sales at all in that family for the period, so there was no denominator to divide by; render it as "no data" rather than 0%. include=trend adds the month-by-month vendor and total series, and the two combine comma-separated (include=families,trend) to return both in one call — that combination is what the Response Example below shows.
GET /vapi/v1/reports/sales_share_by_retailer

Sales Share by Retailer report for the authenticated vendor

Returns the vendor's cost-of-goods share of each retailer's total sales, computed from the nightly sales rollup (data through yesterday). Response envelope: { meta, totals, data: [ {...} ], trend?, pagination }, matching SalesShareResponse. Accepts a custom date range via start_date/end_date (ISO 8601, e.g. 2026-01-01); the range must not exceed 366 days and defaults to the last 30 days. Dates are interpreted in the VENDOR's local timezone (falling back to Pacific Time), not UTC and not the retailer's timezone. Pass include=families,trend to opt into the per-family breakdown and monthly trend. Both are omitted from the response unless requested. Money values on this endpoint are USD DOLLARS, rounded to 2 decimals -- unlike the retailer collections (inventories, sales, products, purchase orders, manifests), which return integer CENTS. Share values are 0-1 ratios. Pagination applies to the data array only; totals covers every retailer matching the filters. Pagination state is reported under meta (consistent with the other VAPI collections) and, for backwards compatibility, is duplicated under the original top-level pagination key. Prefer meta; treat pagination as deprecated. Requires the sales_access permission on the integrator/vendor connection. A connection without it receives 401 "No permission".

Parameters

Name Type In Required Description
vendor_id integer query No Vendor ID (alternative to supplying vendor_token in the auth header)
start_date string query No Start date (ISO 8601, e.g. 2026-01-01). Interpreted in the vendor's local timezone. Required if end_date is given
end_date string query No End date (ISO 8601, e.g. 2026-01-31). Interpreted in the vendor's local timezone. Required if start_date is given
merchant_ids string query No Comma-separated merchant IDs to filter
retailer_ids string query No Comma-separated retailer IDs to filter (the ids returned by /vapi/v1/retailers)
product_family_ids string query No Comma-separated product family IDs to filter
brand_ids string query No Comma-separated core brand IDs to filter (vendor side only)
include string query No Optional sections: families, trend (comma-separated)
page integer query No Page number (default 1)
per_page integer query No Retailer rows per page (default 100, max 1000; larger values are clamped, not rejected)

Example

curl -X GET "https://app.posabit.com/vapi/v1/reports/sales_share_by_retailer" \
  -H "Authorization: Basic BASE64(INTEGRATOR_TOKEN:VENDOR_TOKEN)" \
  -H "Accept: application/json"

Responses

Status Description
200 Success
401 Invalid integrator token, invalid vendor, or missing sales_access permission
422 Invalid or out-of-range dates

Response Example

{
  "meta": {
    "report": "sales_share_by_retailer",
    "vendor_id": 1,
    "period": {
      "start_date": "2026-05-01",
      "end_date": "2026-06-30"
    },
    "currency": "USD",
    "generated_at": "2026-07-01T18:22:04Z"
  },
  "totals": {
    "vendor_cog": 47916.04,
    "total_cog": 125166.63,
    "vendor_share": 0.3828,
    "retailers_with_sales": 124,
    "vendor_share_prior_period": 0.4098,
    "vendor_share_change_pct": -6.6
  },
  "data": [
    {
      "retailer": {
        "id": 3221,
        "name": "The Bong Marche"
      },
      "merchant": {
        "id": 5,
        "name": "POSaBIT Demo"
      },
      "vendor_cog": 4227.0,
      "total_cog": 9675.0,
      "vendor_share": 0.4369,
      "families": [
        {
          "product_family": "Flower",
          "vendor_cog": 1709.0,
          "share": 0.425
        },
        {
          "product_family": "Preroll",
          "vendor_cog": 2518.0,
          "share": 0.602
        },
        {
          "product_family": "Concentrate",
          "vendor_cog": 0.0,
          "share": null
        },
        {
          "product_family": "Uncategorized",
          "vendor_cog": 0.0,
          "share": 0.0
        }
      ]
    },
    {
      "retailer": {
        "id": 4102,
        "name": "Green Vault"
      },
      "merchant": {
        "id": 12,
        "name": "Cascade Holdings"
      },
      "vendor_cog": 2891.5,
      "total_cog": 14350.25,
      "vendor_share": 0.2015,
      "families": [
        {
          "product_family": "Flower",
          "vendor_cog": 1420.0,
          "share": 0.231
        },
        {
          "product_family": "Preroll",
          "vendor_cog": 1105.5,
          "share": 0.348
        },
        {
          "product_family": "Concentrate",
          "vendor_cog": 366.0,
          "share": 0.091
        },
        {
          "product_family": "Uncategorized",
          "vendor_cog": 0.0,
          "share": 0.0
        }
      ]
    }
  ],
  "trend": {
    "months": [
      "May 2026",
      "June 2026"
    ],
    "families": [
      "Flower",
      "Preroll",
      "Concentrate",
      "Uncategorized"
    ],
    "vendor": {
      "Flower": [
        11240.5,
        11890.25
      ],
      "Preroll": [
        9875.0,
        10420.6
      ],
      "Concentrate": [
        2180.44,
        2309.25
      ],
      "Uncategorized": [
        0.0,
        0.0
      ]
    },
    "total": {
      "Flower": [
        29500.0,
        30880.13
      ],
      "Preroll": [
        21400.0,
        22990.5
      ],
      "Concentrate": [
        9800.0,
        10120.0
      ],
      "Uncategorized": [
        240.0,
        236.0
      ]
    }
  },
  "pagination": {
    "page": 1,
    "per_page": 100,
    "total": 124,
    "total_pages": 2
  }
}

Models

0 endpoints

Models

SalesShareResponse

Sales share by retailer. Money values are USD DOLLARS on this endpoint (unlike the retailer collections, which use cents); share values are 0-1 ratios.

Property Type Required Description
meta SalesShareMeta Yes Report identity and window
totals SalesShareTotals Yes Roll-up across every retailer matching the filters
data array (SalesShareRow) Yes One row per retailer, for the requested page
trend SalesShareTrend No Monthly trend. PRESENT ONLY when include=trend was requested
pagination PaginationMeta Yes Pagination state
SalesShareMeta

Identity and window of the report run.

Property Type Required Description
report string Yes Always "sales_share_by_retailer"
vendor_id integer Yes Authenticated vendor id
period SalesSharePeriod Yes Window the report covers
currency string Yes Always "USD"
generated_at string Yes When this response was produced (UTC, ISO 8601)
page integer No Current page number (1-based). Mirrors pagination.page
per_page integer No Rows per page. Mirrors pagination.per_page
total integer No Total retailer rows across all pages. Mirrors pagination.total
total_pages integer No Total number of pages. Mirrors pagination.total_pages
max_per_page integer No Ceiling on per_page. Mirrors pagination.max_per_page
SalesSharePeriod

Inclusive date window the report covers, in the vendor's local timezone.

Property Type Required Description
start_date string Yes First day of the window (ISO 8601 date)
end_date string Yes Last day of the window (ISO 8601 date)
SalesShareTotals

Roll-up across every retailer matching the filters, not just the current page.

Property Type Required Description
vendor_cog float Yes The vendor's cost of goods sold, in DOLLARS
total_cog float Yes All vendors' cost of goods sold at these retailers, in DOLLARS
vendor_share float No vendor_cog / total_cog as a 0-1 ratio. NULL when total_cog is zero
retailers_with_sales integer No Retailers that recorded any sales in the window
vendor_share_prior_period float No Same ratio for the immediately preceding window of equal length. NULL when unavailable
vendor_share_change_pct float No Percentage-point change in share against the prior period. NULL when unavailable
SalesShareRow

One retailer's contribution for the requested window.

Property Type Required Description
retailer SalesShareRetailerRef Yes Retailer reference
merchant SalesShareMerchantRef Yes Merchant that operates the retailer
vendor_cog float Yes The vendor's cost of goods sold at this retailer, in DOLLARS
total_cog float Yes All vendors' cost of goods sold at this retailer, in DOLLARS
vendor_share float No vendor_cog / total_cog as a 0-1 ratio. NULL when total_cog is zero
families array (SalesShareFamily) No Per product family breakdown. PRESENT ONLY when include=families was requested
SalesShareRetailerRef

Retailer reference.

Property Type Required Description
id integer Yes Retailer id (matches /vapi/v1/retailers)
name string No Retailer name
SalesShareMerchantRef

Merchant reference.

Property Type Required Description
id integer No Merchant id. NULL when the retailer's venue has no merchant on record
name string No Merchant name
SalesShareFamily

One product family's contribution within a retailer row.

Property Type Required Description
product_family string Yes Product family name
vendor_cog float Yes The vendor's cost of goods sold in this family, in DOLLARS
share float No This family's share of the retailer's total, as a 0-1 ratio. NULL when the denominator is zero
SalesShareTrend

Parallel arrays describing the monthly trend. Index i of each array refers to months[i].

Property Type Required Description
months array Yes Month labels, oldest first
families array No Product family names present in the trend
vendor array No The vendor's cost of goods sold per month, in DOLLARS
total array No All vendors' cost of goods sold per month, in DOLLARS