Dataset and field reference
This is the exhaustive field catalog for all seven syncable datasets. For each dataset you get the Airtable column, the SKU.io value behind it, the Airtable cell type, and whether an edit in Airtable writes back into SKU.io. For the safety reasoning behind the inbound whitelists, see Inbound safety and the field whitelist.
How to read these tables
- Airtable field — the column label SKU.io provisions in your base and shows in the mapping-grid field picker.
- SKU.io source — the underlying SKU.io attribute (a dot path like
brand.namereads through a relation). - Cell type — the Airtable field type:
text,number,currency,datetime,checkbox, orattachment. - Inbound-writable? — whether editing that column in Airtable can change SKU.io. Yes means the field is on the dataset's inbound whitelist; No (outbound-only) means SKU.io pushes it out but ignores any edit; No (read-only) / No (computed) are pushed but never accepted back; Key is the merge column and is never writable.
Only three datasets accept any inbound writes at all — Products, Sales Orders, and Suppliers. The other four (Inventory Levels, Sales Order Lines, Purchase Orders, PO Lines) are outbound-only: SKU.io writes them to Airtable and never reads edits back.
Every dataset's first field is the synthetic SKU.io ID (sku_io_id) key. SKU.io upserts rows by matching this column, so it must stay unique per record — do not edit it in Airtable.
Every datetime column — Order Date, Updated At, Purchase Order Date, and the rest — is written to Airtable in UTC, as an ISO-8601 timestamp. The SKU.io UI displays date-times in your application timezone, so the same value will read differently in Airtable. Account for the offset when you build date filters, grouped views, or dashboards in your base.
Datasets at a glance
| Dataset | Two-way? | Merge key | Delete behavior | Auto-create? |
|---|---|---|---|---|
| Products | Yes | Product SKU (falls back to primary key) | Soft-delete (has Archived) | Yes (opt-in) |
| Inventory Levels | No (outbound-only) | Composite product_id:warehouse_id | Hard-delete | No |
| Sales Orders | Yes | sales_order_number | Soft-delete (has Archived) | No |
| Sales Order Lines | No (outbound-only) | Line primary key | Hard-delete | No |
| Purchase Orders | No (outbound-only) | purchase_order_number | Soft-delete (has Archived) | No |
| PO Lines | No (outbound-only) | Line primary key | Hard-delete | No |
| Suppliers | Yes | Numeric supplier database id | Soft-delete (has Archived) | No |
Two-way datasets accept edits back only for the narrow field sets listed under each dataset below. Everything else is outbound-only.
Products
The richest dataset, and the one with the widest inbound whitelist. The merge key (sku_io_id) is the product SKU, not the database id — if a product has no SKU, SKU.io falls back to the primary key.
| Airtable field | SKU.io source | Cell type | Inbound-writable? |
|---|---|---|---|
| SKU.io ID | sku_io_id (product SKU) | text | Key |
| Name | name | text | Yes |
| Barcode | barcode | text | Yes |
| MPN | mpn | text | Yes |
| HTS Code | hts_code | text | Yes |
| Type | type | text | No (outbound-only) |
| Weight | weight | number | Yes |
| Weight Unit | weight_unit | text | No (outbound-only) |
| Length | length | number | Yes |
| Width | width | number | Yes |
| Height | height | number | Yes |
| Average Cost | average_cost | currency | No (read-only) |
| Unit Cost | unit_cost | currency | Yes |
| Price | price | currency | No (outbound-only) |
| Brand | brand.name | text | Yes |
| Images | images | attachment | No (outbound-only) |
| Gross Margin % | gross_margin_pct | number | No (computed) |
| On Hand | on_hand | number | No (computed) |
| Units Sold (90d) | units_sold_90d | number | No (computed) |
| Days of Cover | days_of_cover | number | No (computed) |
| Sell-through % (90d) | sell_through_pct | number | No (computed) |
| Archived | is_archived | checkbox | No (outbound-only) |
| Updated At | updated_at | datetime | No (outbound-only) |
Inbound-only relations (no outbound column): two more fields — tags and category — accept inbound writes but have no catalog column that SKU.io pushes outbound. You map them explicitly to Airtable columns of your choosing. Their inbound behavior is described in the Notes below.
Products is the only dataset with relation-backed inbound writes. Every field marked Yes above is written verbatim through the product repository, except brand, and the two relation-only fields (tags, category) behave as described below. Everything else — inventory, average_cost, pricing, the computed metrics, type, weight_unit, is_archived, and updated_at — is ignored inbound.
Notes:
unit_costis the only writable cost.average_costis read-only andpriceis outbound-only, so SKU.io never lets Airtable overwrite either — both are hard-excluded from inbound writes.- Brand is advertised outbound as the dotted path
brand.name, but inbound normalizes it to the bare relationbrandfor diffing and applying. An inbound brand write matches an existing brand by name, or creates one if it does not exist (first-or-create by name). - Tags syncs the full tag set. It accepts an array or a comma-separated string; values are trimmed, de-duplicated, sorted, and comma-joined for stable diffing.
- Category attaches an existing category by exact name only. Categories form a path-based tree, so SKU.io never creates one — an unknown name is silently skipped.
- Unmatched Airtable rows can auto-create a product when the mapping opts in: SKU.io creates a new product with
skuset to the merge key andtype= standard, then applies the scalar and relation fields. A merge key that collides with an existing SKU raises a unique-constraint error rather than overwriting the existing product.
Inventory Levels
Outbound-only — inventory is never writable from Airtable. Each row is a per-product, per-warehouse stock level. The merge key is a composite of product_id and warehouse_id (joined as product_id:warehouse_id), not a single id.
| Airtable field | SKU.io source | Cell type | Inbound-writable? |
|---|---|---|---|
| SKU.io ID | sku_io_id (product_id:warehouse_id) | text | Key |
| SKU | product.sku | text | No (outbound-only) |
| Warehouse | warehouse.name | text | No (outbound-only) |
| Available | inventory_available | number | No (outbound-only) |
| On Hand | inventory_total | number | No (outbound-only) |
| Allocated | inventory_allocated | number | No (outbound-only) |
| Avg Cost | inventory_avg_cost | currency | No (outbound-only) |
| Updated At | updated_at | datetime | No (outbound-only) |
This is a hard-delete dataset: it has no Archived column, so a removed level is deleted from Airtable rather than flagged. If a mapping's delete mode is set to flag, SKU.io coerces it to delete for this dataset. The On Hand column here is per-warehouse inventory_total — distinct from the product-level On Hand metric on the Products dataset, which aggregates stock across warehouses.
Sales Orders
Inbound-capable, but only descriptive customer metadata flows back — never the statuses or dates that drive the fulfillment and financial state machine. The merge key is the sales_order_number, not the database id.
| Airtable field | SKU.io source | Cell type | Inbound-writable? |
|---|---|---|---|
| SKU.io ID | sku_io_id (sales_order_number) | text | Key |
| Order Status | order_status | text | No (outbound-only) |
| Fulfillment Status | fulfillment_status | text | No (outbound-only) |
| Payment Status | payment_status | text | No (outbound-only) |
| Order Date | order_date | datetime | No (outbound-only) |
| Customer Name | customer_name | text | Yes (PII) |
| Customer Email | customer_email | text | Yes (PII) |
| Customer Company | customer_company | text | Yes (PII) |
| Customer Phone | customer_phone | text | Yes (PII) |
| Customer PO | customer_po_number | text | Yes |
| Customer Memo | memo_for_customer | text | Yes |
| Archived | is_archived | checkbox | No (outbound-only) |
| Updated At | updated_at | datetime | No (outbound-only) |
Notes:
- Editing a status or
order_datecolumn in Airtable is a no-op. Those fields are excluded from the inbound whitelist and never mutate the order. - No auto-create. An unmatched Airtable row is queued for review — SKU.io never conjures a sales order from a spreadsheet row. Writes match an order by
sales_order_number. - Only the six descriptive customer fields write back (the ones marked Yes above:
customer_name,customer_email,customer_company,customer_phone,customer_po_number,memo_for_customer).order_status,fulfillment_status,payment_status,order_date, and tracking are deliberately excluded — they drive the fulfillment and financial state machine, so an Airtable edit to any of them is ignored inbound. - The four Customer fields are flagged PII in the field picker (see PII-flagged fields).
Sales Order Lines
Outbound-only. Each row is a single line on a sales order. The merge key defaults to the line's database primary key.
| Airtable field | SKU.io source | Cell type | Inbound-writable? |
|---|---|---|---|
| SKU.io ID | sku_io_id (line primary key) | text | Key |
| Order Number | salesOrder.sales_order_number | text | No (outbound-only) |
| SKU | product.sku | text | No (outbound-only) |
| Quantity | quantity | number | No (outbound-only) |
| Price | amount | currency | No (outbound-only) |
| Updated At | updated_at | datetime | No (outbound-only) |
This is a hard-delete dataset — it has no Archived column, so a removed line is deleted from Airtable, never flagged.
Purchase Orders
Outbound-only. The merge key is the purchase_order_number.
| Airtable field | SKU.io source | Cell type | Inbound-writable? |
|---|---|---|---|
| SKU.io ID | sku_io_id (purchase_order_number) | text | Key |
| Order Status | order_status | text | No (outbound-only) |
| Receipt Status | receipt_status | text | No (outbound-only) |
| Total Cost | total_cost | currency | No (outbound-only) |
| Total Quantity | total_quantity | number | No (outbound-only) |
| Supplier | supplier.name | text | No (outbound-only) |
| Order Date | purchase_order_date | datetime | No (outbound-only) |
| Archived | is_archived | checkbox | No (outbound-only) |
| Updated At | updated_at | datetime | No (outbound-only) |
Unlike the line datasets, Purchase Orders has an Archived column, so it is a soft-delete dataset: a mapping's flag delete mode works here and marks removed rows as archived rather than deleting them.
PO Lines
Outbound-only. The dataset's display label is PO Lines (its SKU.io identifier is purchase_order_lines). The merge key defaults to the line's database primary key.
| Airtable field | SKU.io source | Cell type | Inbound-writable? |
|---|---|---|---|
| SKU.io ID | sku_io_id (line primary key) | text | Key |
| PO Number | purchaseOrder.purchase_order_number | text | No (outbound-only) |
| SKU | product.sku | text | No (outbound-only) |
| Quantity | quantity | number | No (outbound-only) |
| Unit Cost | amount | currency | No (outbound-only) |
| Updated At | updated_at | datetime | No (outbound-only) |
This is a hard-delete dataset — no Archived column, so removed lines are deleted from Airtable, never flagged.
Suppliers
Inbound-capable, but only contact and company descriptors flow back. The merge key is the numeric supplier database id.
| Airtable field | SKU.io source | Cell type | Inbound-writable? |
|---|---|---|---|
| SKU.io ID | sku_io_id (supplier id) | text | Key |
| Name | name | text | Yes |
| Company | company_name | text | Yes |
| Contact Name | primary_contact_name | text | Yes (PII) |
email | text | Yes (PII) | |
| Phone | messaging_phone | text | Yes (PII) |
| Website | website | text | Yes |
| Archived | is_archived | checkbox | No (outbound-only) |
| Updated At | updated_at | datetime | No (outbound-only) |
Notes:
- Operational config is never mutable from Airtable — lead times, PO automation, default warehouses, payment terms, and deposits have no catalog column at all, so they cannot be exported or written back.
- No auto-create in v1. An unmatched Airtable row is queued for review, never created as a new supplier.
- Only the six contact/company descriptors write back (the ones marked Yes above:
name,company_name,primary_contact_name,email,messaging_phone,website). Operational fields are excluded at the catalog level, not merely at the whitelist — there is no column to write. - Because the merge key must be a numeric SKU.io id, a non-numeric value in the key column resolves to no supplier.
- The three contact fields are flagged PII (see PII-flagged fields).
Computed product metric columns
The Products dataset exposes five live read-only analytics columns. SKU.io recomputes them from live data on every sync and pushes them out, but never accepts them back — they are not on the Products inbound whitelist, so an Airtable edit to any of them is silently ignored. SKU.io only queries these metrics when the column is actually mapped.
| Airtable field | SKU.io source | How it is computed |
|---|---|---|
| Gross Margin % | gross_margin_pct | (price − average_cost) / price × 100, rounded to 1 decimal. Null when price is 0. |
| On Hand | on_hand | Current on-hand stock aggregated across warehouses. |
| Units Sold (90d) | units_sold_90d | Fulfilled units over the trailing 90 days. |
| Days of Cover | days_of_cover | on_hand ÷ (units_sold_90d ÷ 90), rounded to 1 decimal. Null when no units sold. |
| Sell-through % (90d) | sell_through_pct | units_sold_90d ÷ (units_sold_90d + on_hand) × 100, rounded to 1 decimal. Null when there is no stock and no sales. |
Days of Cover and Sell-through % are null when there are no sales (or no stock and no sales) to divide by. Alongside average_cost, price, images, is_archived, and updated_at, these five metrics are outbound-only decoration — editing them in Airtable has no effect on SKU.io. Note that the Products On Hand metric aggregates stock across warehouses, whereas the On Hand column on Inventory Levels is a single warehouse's inventory_total.
PII-flagged fields
Customer and contact fields — names, emails, phones, and companies — are flagged as PII in the mapping-grid field picker so you knowingly opt in before exporting personal data to Airtable.
| Dataset | PII fields |
|---|---|
| Sales Orders | Customer Name, Customer Email, Customer Company, Customer Phone |
| Suppliers | Contact Name, Email, Phone |
Related
- Inbound safety and the field whitelist — why only these narrow field sets write back.
- Sync-mapping settings reference — delete modes, inbound toggles, and per-field mapping options.
- How Airtable sync works — the outbound merge-and-archive lifecycle behind these tables.