Documentation Index Fetch the complete documentation index at: https://docs.flexprice.io/llms.txt
Use this file to discover all available pages before exploring further.
Overview
This guide walks through the complete integration workflow between Flexprice and QuickBooks Online, from initial setup to invoice sync and payment reconciliation.
Integration Type : One-way sync (Flexprice → QuickBooks)
Key Capabilities :
✅ Automatic invoice sync
✅ On-demand customer creation
✅ Automatic item (product/service) creation
✅ Inbound Payment sync
Step-by-Step Workflow
Phase 1: Initial Setup
Create QuickBooks App
Go to Intuit Developer Portal
Create new app for QuickBooks Online
Configure OAuth 2.0 settings
Copy Client ID and Client Secret
Duration : 5-7 minutes
Configure Webhook
In Intuit Developer Portal, go to Webhooks
Add webhook endpoint: https://api.cloud.flexprice.io/v1/webhooks/quickbooks/{tenant_id}/{environment_id}
Subscribe to Payment entity events
Copy webhook verifier token
Duration : 2-3 minutes
Create Connection in Flexprice
Navigate to Integrations
Go to QuickBooks and click “Add a connection”
Enter credentials and configuration
Complete OAuth authorization flow
Verify connection is active
Duration : 3-5 minutes
Total Setup Time : ~10 minutes (one-time)
Phase 2: Plan and Price Setup
Create Plan in Flexprice
Create a pricing plan with charges: Example Plan: “Pro Plan”
Recurring charge: $99/month (Flat fee)
Metered charge: $0.01 per API call (Usage-based)
{
"name" : "Pro Plan" ,
"interval" : "month" ,
"prices" : [
{
"id" : "price_recurring_01" ,
"display_name" : "Monthly Fee" ,
"amount" : 99.00 ,
"type" : "recurring"
},
{
"id" : "price_metered_02" ,
"display_name" : "API Calls" ,
"unit_amount" : 0.01 ,
"meter" : "api_calls" ,
"type" : "usage"
}
]
}
QuickBooks Connection Active
Verify QuickBooks connection:
Status: Active
Invoice sync: Enabled
Income Account: Configured
No action needed - Items will be created automatically during first invoice sync
Phase 3: Customer Subscription
Customer Subscribes
Customer creates a subscription to Pro Plan: {
"customer_id" : "cust_abc123" ,
"plan_id" : "plan_pro" ,
"start_date" : "2025-01-01"
}
Subscription Period Runs
During the subscription period:
Customer uses 4,500 API calls
Usage is tracked via events
Billing period ends on 2025-01-31
Phase 4: Invoice Generation
Invoice Auto-Generated
At end of billing period, Flexprice generates invoice: {
"id" : "inv_xyz789" ,
"customer_id" : "cust_abc123" ,
"line_items" : [
{
"price_id" : "price_recurring_01" ,
"description" : "Pro Plan - Monthly Fee" ,
"amount" : 99.00 ,
"quantity" : 1
},
{
"price_id" : "price_metered_02" ,
"description" : "API Calls" ,
"amount" : 45.00 ,
"quantity" : 4500 ,
"unit_price" : 0.01
}
],
"total" : 144.00 ,
"status" : "open"
}
Sync Trigger Check
Flexprice checks if invoice should sync:
✅ QuickBooks connection exists
✅ Connection is active
✅ Invoice sync is enabled
✅ Customer has valid data
→ Proceed with sync
Phase 5: Customer Sync
Check Customer Mapping
Query entity_integration_mapping: SELECT * FROM entity_integration_mapping
WHERE entity_id = 'cust_abc123'
AND entity_type = 'customer'
AND provider_type = 'quickbooks'
Result : Not found → Customer needs to be created
Create Customer in QuickBooks
Create customer via QuickBooks API: Request :POST /v 3 /company/{ realmId }/customer
{
"DisplayName" : "Acme Corporation" ,
"PrimaryEmailAddr" : {
"Address" : "billing@acme.com"
},
"BillAddr" : {
"Line1" : "123 Main St" ,
"City" : "San Francisco" ,
"CountrySubDivisionCode" : "CA" ,
"PostalCode" : "94105" ,
"Country" : "USA"
}
}
Response :{
"Id" : "67" ,
"DisplayName" : "Acme Corporation" ,
"PrimaryEmailAddr" : {
"Address" : "billing@acme.com"
}
}
Store Customer Mapping
Create mapping record: {
"entity_id" : "cust_abc123" ,
"entity_type" : "customer" ,
"provider_type" : "quickbooks" ,
"provider_entity_id" : "67" ,
"metadata" : {
"synced_at" : "2025-01-31T10:00:00Z" ,
"quickbooks_customer_display_name" : "Acme Corporation" ,
"quickbooks_customer_primary_email_addr_address" : "billing@acme.com"
}
}
Phase 6: Item Creation
Process Line Item 1 (Recurring)
Price : price_recurring_01 (Monthly Fee)
Check mapping → Not found
Query QuickBooks for item → Not found
Create service item:
POST /v 3 /company/{ realmId }/item
{
"Name" : "Pro Plan-Monthly Fee" ,
"Description" : "price_recurring_01" ,
"Type" : "Service" ,
"IncomeAccountRef" : {
"value" : "79" ,
"name" : "Services"
}
}
QB Response: {"Id": "125"}
Store mapping: price_recurring_01 → 125
Process Line Item 2 (Metered)
Price : price_metered_02 (API Calls)
Check mapping → Not found
Query QuickBooks for item → Not found
Create service item:
POST /v 3 /company/{ realmId }/item
{
"Name" : "Pro Plan-API Calls" ,
"Description" : "price_metered_02" ,
"Type" : "Service" ,
"IncomeAccountRef" : {
"value" : "79" ,
"name" : "Services"
}
}
QB Response: {"Id": "126"}
Store mapping: price_metered_02 → 126
Phase 7: Invoice Sync
Create Invoice in QuickBooks
Create invoice with all line items: POST /v 3 /company/{ realmId }/invoice
{
"DocNumber" : "INV-001" ,
"TxnDate" : "2025-01-31" ,
"DueDate" : "2025-02-14" ,
"CustomerRef" : {
"value" : "67"
},
"Line" : [
{
"DetailType" : "SalesItemLineDetail" ,
"Amount" : 99.00 ,
"Description" : "Pro Plan - Monthly Fee" ,
"SalesItemLineDetail" : {
"ItemRef" : {
"value" : "125" ,
"name" : "Pro Plan-Monthly Fee"
},
"UnitPrice" : 99.00 ,
"Qty" : 1
}
},
{
"DetailType" : "SalesItemLineDetail" ,
"Amount" : 45.00 ,
"Description" : "API Calls" ,
"SalesItemLineDetail" : {
"ItemRef" : {
"value" : "126" ,
"name" : "Pro Plan-API Calls"
},
"UnitPrice" : 0.01 ,
"Qty" : 4500
}
}
],
"TotalAmt" : 144.00
}
QB Response :{
"Id" : "219" ,
"DocNumber" : "INV-001" ,
"TotalAmt" : 144.00 ,
"Balance" : 144.00
}
Store Invoice Mapping
Create mapping record: {
"entity_id" : "inv_xyz789" ,
"entity_type" : "invoice" ,
"provider_type" : "quickbooks" ,
"provider_entity_id" : "219" ,
"metadata" : {
"synced_at" : "2025-01-31T10:05:00Z" ,
"quickbooks_invoice_doc_number" : "INV-001"
}
}
Update Flexprice Invoice
Update invoice metadata: {
"id" : "inv_xyz789" ,
"metadata" : {
"quickbooks_invoice_id" : "219" ,
"quickbooks_synced_at" : "2025-01-31T10:05:00Z" ,
"quickbooks_status" : "pending"
}
}
Phase 8: Payment Recording (in QuickBooks)
Accountant Records Payment
Your accounting team records payment in QuickBooks:
Open QuickBooks Desktop/Online
Navigate to invoice #219
Click “Receive Payment”
Enter payment details:
Amount: $144.00
Date: 2025-02-05
Method: Bank Transfer
Mark invoice as paid
QuickBooks Creates Payment Entity
QuickBooks creates a Payment record: {
"Id" : "222" ,
"TxnDate" : "2025-02-05" ,
"TotalAmt" : 144.00 ,
"CustomerRef" : { "value" : "67" },
"Line" : [
{
"Amount" : 144.00 ,
"LinkedTxn" : [
{
"TxnId" : "219" ,
"TxnType" : "Invoice"
}
]
}
]
}
Phase 9: Webhook Notification
QuickBooks Sends Webhook
QuickBooks sends webhook to Flexprice: Webhook Payload :POST /v 1 /webhooks/quickbooks/{ tenant_id }/{ environment_id }
{
"eventNotifications" : [
{
"realmId" : "1234567890" ,
"dataChangeEvent" : {
"entities" : [
{
"name" : "Payment" ,
"id" : "222" ,
"operation" : "Create" ,
"lastUpdated" : "2025-02-05T14:30:00.000Z"
}
]
}
}
]
}
Headers :intuit-signature: <HMAC-SHA256 signature>
Flexprice Verifies Webhook
Verify webhook signature (if verifier token configured)
Check payment sync is enabled
Extract payment ID: “222”
Phase 10: Payment Reconciliation
Fetch Payment Details
Call QuickBooks API to get full payment: GET /v3/company/{realmId}/payment/222
Response :{
"Id" : "222" ,
"TotalAmt" : 144.00 ,
"TxnDate" : "2025-02-05" ,
"Line" : [
{
"Amount" : 144.00 ,
"LinkedTxn" : [
{
"TxnId" : "219" ,
"TxnType" : "Invoice"
}
]
}
]
}
Extract : QuickBooks Invoice ID = “219”
Find Flexprice Invoice
Query entity_integration_mapping: SELECT * FROM entity_integration_mapping
WHERE provider_entity_id = '219'
AND entity_type = 'invoice'
AND provider_type = 'quickbooks'
Result : Flexprice Invoice ID = inv_xyz789
Update Invoice Status
Update invoice in Flexprice: {
"id" : "inv_xyz789" ,
"payment_status" : "SUCCEEDED" ,
"paid_at" : "2025-02-05T14:30:00Z" ,
"amount_paid" : 144.00 ,
"amount_remaining" : 0.00 ,
"metadata" : {
"payment_method" : "offline" ,
"payment_recorded_by" : "quickbooks" ,
"quickbooks_payment_id" : "222" ,
"quickbooks_invoice_id" : "219" ,
"payment_synced_at" : "2025-02-05T14:30:00Z"
}
}
Reconciliation Complete
Invoice is now marked as paid in Flexprice:
✅ Payment status: SUCCEEDED
✅ Amount paid: $144.00
✅ Linked to QuickBooks payment
✅ Audit trail maintained
Next Invoice (Same Customer)
When the next billing cycle arrives:
Invoice Generated
Second invoice generated for same customer
Customer Check
✅ Mapping exists → Use QB Customer ID “67” (no creation needed)
Item Check
✅ Mappings exist → Use QB Item IDs “125” and “126” (no creation needed)
Invoice Created
Only invoice is created in QuickBooks (reusing customer and items)
Result : Subsequent invoices sync much faster since customer and items already exist.
Key Integration Points
1. Entity Integration Mapping
Purpose : Track relationships between Flexprice and QuickBooks entities
Entities Tracked :
Customers: cust_abc123 ↔ QB Customer 67
Prices/Items: price_recurring_01 ↔ QB Item 125
Invoices: inv_xyz789 ↔ QB Invoice 219
Why It Matters :
Prevents duplicate entity creation
Enables bidirectional lookups
Maintains data integrity
2. Sync Configuration
Invoice Sync :
{
"invoice" : {
"inbound" : false ,
"outbound" : true
}
}
Payment Sync :
{
"payment" : {
"inbound" : true ,
"outbound" : false
}
}
3. Webhook Processing
Flow :
QuickBooks sends webhook → Flexprice
Verify signature (optional)
Fetch full payment details
Find linked invoice
Update invoice status
Return 200 OK immediately
Security :
HMAC-SHA256 signature verification
HTTPS only
Idempotency handling
Rate limiting
Error Handling
Common Scenarios
Scenario Handling Result Customer already exists Use existing QB customer No error Item already exists Use existing QB item No error Invoice already synced Skip sync, return mapping No error Missing Income Account Return error, block sync User must configure QB API rate limit Retry with exponential backoff Eventual success OAuth token expired Auto-refresh token, retry Transparent to user Webhook signature fail Log warning, skip processing Security measure
Graceful Degradation
Philosophy : Integration failures should NOT break core Flexprice functionality
Example :
Invoice creation in Flexprice: ✅ Success
QB sync fails due to API error: ⚠️ Logged, not blocking
Invoice is still accessible in Flexprice
Manual retry available
First Invoice Sync
Time : ~5-10 seconds
Operations : Customer creation + 2 item creations + invoice creation
Subsequent Invoice Syncs
Time : ~2-3 seconds
Operations : Invoice creation only (reuses existing customer and items)
Optimization Strategies
✅ Entity mapping cache
✅ Parallel API calls where possible
✅ Connection pooling
✅ Automatic token refresh
Troubleshooting Guide
Invoice Not Syncing
Verify QB connection is active
Check OAuth token is valid
Test API connectivity
Verify invoice sync is enabled
Check sync_config.invoice.outbound = true
Ensure no sync filters blocking
Verify Income Account ID is configured
Ensure account exists in QB and is active
Query QB to confirm account type
Payment Not Updating
Check Webhook Configuration
Verify webhook endpoint is correct
Check webhook events are subscribed
Review webhook delivery logs in Intuit portal
Check Payment Sync Setting
Verify payment sync is enabled
Check sync_config.payment.inbound = true
Ensure webhook verifier token is configured (optional)
Verify invoice was synced to QB
Check entity_integration_mapping exists
Confirm QB invoice ID matches