Product Tables
Product tables allow you to include structured pricing information in your documents. They’re ideal for quotes, invoices, order forms, and any document that needs to present products or services with pricing.
Overview
A product table displays:
Products/Services with descriptions
Quantities for each line item
Unit prices and calculated totals
Subtotals, VAT, and grand totals
Creating Product Table Fields
Product tables are added as document fields. First, create a document, then add a product table field.
Add a Product Table to a Document
curl -X POST https://app.sajn.se/api/v1/documents/doc_123/fields \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "PRODUCT_TABLE",
"page": 1,
"position": {
"x": 50,
"y": 300,
"width": 500,
"height": 200
},
"fieldMeta": {
"products": [
{
"name": "Website Design",
"description": "Custom website design and development",
"quantity": 1,
"unitPrice": 25000,
"unit": "st"
},
{
"name": "Hosting (Annual)",
"description": "Web hosting for one year",
"quantity": 1,
"unitPrice": 3600,
"unit": "year"
},
{
"name": "Support Hours",
"description": "Technical support and maintenance",
"quantity": 10,
"unitPrice": 950,
"unit": "hour"
}
],
"currency": "SEK",
"vatRate": 25,
"showVat": true
}
}'
Table Structure
Product Line Item Fields
Field Type Required Description namestring Yes Product or service name descriptionstring No Detailed description quantitynumber Yes Number of units unitPricenumber Yes Price per unit (in minor currency units or major) unitstring No Unit type (e.g., “st”, “hour”, “month”) discountnumber No Discount percentage for this line
Table Configuration
Field Type Description currencystring Currency code (e.g., “SEK”, “EUR”, “USD”) vatRatenumber VAT/tax percentage (e.g., 25 for 25%) showVatboolean Whether to display VAT separately includesVatboolean Whether prices include VAT columnsarray Custom column configuration
Calculations
Product tables automatically calculate:
Line Item Total
lineTotal = quantity × unitPrice × (1 - discount/100)
Subtotal
subtotal = sum of all lineTotals
VAT Amount
vatAmount = subtotal × (vatRate / 100)
Grand Total
grandTotal = subtotal + vatAmount
Example Calculation
For the example above:
Product Quantity Unit Price Line Total Website Design 1 25,000 SEK 25,000 SEK Hosting (Annual) 1 3,600 SEK 3,600 SEK Support Hours 10 950 SEK 9,500 SEK
Amount Subtotal 38,100 SEK VAT (25%) 9,525 SEK Grand Total 47,625 SEK
Complete Example: Quote Document
Create a quote with product table, signers, and custom fields:
# Step 1: Create the document
curl -X POST https://app.sajn.se/api/v1/documents \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Quote - Website Project for Acme Corp",
"type": "SIGNABLE",
"expiresAt": "2024-02-28T23:59:59Z",
"documentMeta": {
"subject": "Quote for your website project",
"message": "Please review our quote and sign to accept."
},
"signers": [
{
"name": "Anna Andersson",
"email": "anna@acme.se",
"role": "SIGNER",
"deliveryMethod": "EMAIL",
"requiredSignature": "DRAWING"
}
],
"customFields": [
{
"key": "quote_number",
"value": "Q-2024-0042"
},
{
"key": "valid_until",
"value": "2024-02-28"
}
]
}'
# Step 2: Add the product table
curl -X POST https://app.sajn.se/api/v1/documents/doc_123/fields \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "PRODUCT_TABLE",
"page": 1,
"position": {
"x": 50,
"y": 250,
"width": 500,
"height": 250
},
"fieldMeta": {
"products": [
{
"name": "Discovery & Planning",
"description": "Requirements gathering and project planning",
"quantity": 1,
"unitPrice": 15000
},
{
"name": "UI/UX Design",
"description": "User interface and experience design",
"quantity": 1,
"unitPrice": 35000
},
{
"name": "Frontend Development",
"description": "React-based frontend implementation",
"quantity": 1,
"unitPrice": 45000
},
{
"name": "Backend Development",
"description": "API and database development",
"quantity": 1,
"unitPrice": 55000
},
{
"name": "Testing & QA",
"description": "Quality assurance and testing",
"quantity": 1,
"unitPrice": 15000
}
],
"currency": "SEK",
"vatRate": 25,
"showVat": true
}
}'
Styling Product Tables
Column Configuration
Customize which columns appear and their order:
{
"fieldMeta" : {
"columns" : [
{ "key" : "name" , "label" : "Product" , "width" : 200 },
{ "key" : "description" , "label" : "Description" , "width" : 150 },
{ "key" : "quantity" , "label" : "Qty" , "width" : 50 },
{ "key" : "unitPrice" , "label" : "Unit Price" , "width" : 80 },
{ "key" : "lineTotal" , "label" : "Total" , "width" : 80 }
],
"products" : [ ... ]
}
}
{
"fieldMeta" : {
"currency" : "SEK" ,
"currencySymbol" : "kr" ,
"currencyPosition" : "after" ,
"decimalPlaces" : 2 ,
"thousandsSeparator" : " " ,
"decimalSeparator" : ","
}
}
This formats prices as: 25 000,00 kr
Use Cases
Quotes and Proposals
Present pricing for proposed work with clear line items:
{
"products" : [
{ "name" : "Consulting" , "quantity" : 40 , "unitPrice" : 1500 , "unit" : "hours" },
{ "name" : "Implementation" , "quantity" : 1 , "unitPrice" : 75000 , "unit" : "project" },
{ "name" : "Training" , "quantity" : 2 , "unitPrice" : 15000 , "unit" : "days" }
]
}
Invoices
Bill for delivered goods or services:
{
"products" : [
{ "name" : "Product A" , "quantity" : 100 , "unitPrice" : 150 },
{ "name" : "Product B" , "quantity" : 50 , "unitPrice" : 299 },
{ "name" : "Shipping" , "quantity" : 1 , "unitPrice" : 500 }
]
}
Allow customers to sign off on orders:
{
"products" : [
{ "name" : "Annual License" , "quantity" : 10 , "unitPrice" : 9990 , "unit" : "users" },
{ "name" : "Premium Support" , "quantity" : 1 , "unitPrice" : 25000 , "unit" : "year" },
{ "name" : "Onboarding" , "quantity" : 1 , "unitPrice" : 15000 }
]
}
Service Agreements
Define service packages and pricing:
{
"products" : [
{ "name" : "Basic Plan" , "description" : "Core features" , "quantity" : 12 , "unitPrice" : 999 , "unit" : "months" },
{ "name" : "Setup Fee" , "quantity" : 1 , "unitPrice" : 5000 },
{ "name" : "API Access" , "quantity" : 12 , "unitPrice" : 500 , "unit" : "months" }
]
}
Updating Product Tables
Update Products
Modify the product list on an existing field:
curl -X PATCH https://app.sajn.se/api/v1/documents/doc_123/fields/field_456 \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"fieldMeta": {
"products": [
{
"name": "Updated Product",
"quantity": 5,
"unitPrice": 1000
}
]
}
}'
Product tables can only be modified while the document is in draft status. Once sent for signing, the table is locked.
Best Practices
Product names should be immediately understandable. Avoid internal codes or abbreviations that signers won’t recognize.
Add descriptions for complex items
Use the description field to clarify what’s included in each line item, especially for services.
In B2B contexts, buyers often need to see VAT separately for accounting. Enable showVat: true.
Ensure the currency matches your business context and is clearly displayed.
Verify totals before sending
Double-check that calculated totals match your expectations before sending the document.
For quotes and proposals, consider adding text fields with payment terms, validity period, and conditions.
Next Steps
Creating Documents Learn document creation basics
Templates and Forms Create reusable templates with product tables
Document Fields API Full field API documentation
Send for Signing Send documents to signers