Import a Supplier Invoice via API
Use this guide to import supplier (purchase) invoices into Pennylane using the API — for example, from your ERP, OCR, or document capture tool.
Goal
This tutorial explains how to automatically import supplier invoices so they appear in your workspace, linked to the right supplier and ready for accounting and reconciliation.
You will learn how to:
- Upload a supplier invoice file (PDF)
- Import the invoice via the API
- (Optional) Categorize it for reporting
End Result
Your supplier invoice appears in Pennylane, linked to the right supplier and ledger accounts, fully integrated into your accounting workflow.
Who is this for?
Developers and partners building integrations that sync supplier invoices from external systems into Pennylane.
Authentication
Partner integrations must use OAuth 2.0.
In sandbox, you can test with a Company API token, but OAuth 2.0 is required for Marketplace production integrations.
Before You Get Started
Required scopes (Company API v2)
| Scope | Features |
|---|---|
supplier_invoices:all | Create or import supplier invoices |
file_attachments:all | Upload and attach supplier invoice PDFs |
(optional) ledger_accounts:readonly | Retrieve account IDs for accurate accounting mapping |
(optional) categories:all | Categorize invoices for reporting |
You will need:
- A Pennylane company selected through OAuth consent
- Your OAuth access token (or a Company token in sandbox)
- A valid
supplier_id(existing or newly created) - A valid invoice file (PDF) to attach
- (Optional) ledger account IDs — e.g., 60x for purchases/expenses, 4456 for deductible VAT, 401 for suppliers
IDs are company-specific
Supplier and ledger account IDs differ per company. Store them per tenant to avoid mismatches.
See also:
- Authentication Overview
- Understand V2 Scopes
Step 1 | (Optional) Verifying Authentication
Before importing invoices, confirm that your token and environment are correctly configured.
curl https://app.pennylane.com/api/external/v2/me \
-H "Authorization: Bearer <ACCESS_TOKEN>"✅ Expected response:
200 OK - authentication successful.
Tip: Run this check when setting up your integration for the first time, or when switching between **sandbox **and production.
Step 2 | Uploading the Invoice File
Before importing the supplier invoice, upload the PDF file to Pennylane.
curl --request POST \
--url https://app.pennylane.com/api/external/v2/file_attachments \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: multipart/form-data" \
-F [email protected]✅ Result
The API returns a JSON object containing an id — use this file_attachment_id in the next step.
Example response:
{
"id": 13245,
"filename": "invoice-october.pdf",
"status": "uploaded"
}Accepted file format
Only PDF files are supported for supplier invoice imports.
The
/file_attachmentsendpoint accepts files up to 100 MB.Uploading another format for an invoice will return a validation error (typically
400 Bad Request).
Step 3 | Importing the Supplier Invoice
Now that your invoice file is uploaded, use the import endpoint to create the corresponding invoice in Pennylane.
curl --request POST \
--url https://app.pennylane.com/api/external/v2/supplier_invoices/import \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"file_attachment_id": 13245,
"supplier_id": 98123,
"date": "2025-10-01",
"deadline": "2025-10-31",
"currency_amount_before_tax": "100.00",
"currency_tax": "20.00",
"currency_amount": "120.00",
"invoice_lines": [
{
"ledger_account_id": 601002,
"currency_amount": "120.00",
"currency_tax": "20.00",
"vat_rate": "FR_200"
}
]
}'✅ Result
The invoice is created and appears in your Pennylane workspace, linked to the specified supplier.
Tip: Amount field types
All numeric amounts (e.g.
currency_amount,currency_tax,currency_amount_before_tax) must be provided as strings, not numbers.
Example response:
{
"id": 4431,
"status": "imported",
"supplier_name": "ACME Office Supplies",
"currency_amount": "120.00"
}Important
The sum of all
invoice_lines.currency_amountvalues must equal the totalcurrency_amount.Otherwise, the API returns:
422 Unprocessable Entity — Entry lines are not balanced.
Ledger Account Mapping
If you omit the
ledger_account_id, Pennylane automatically applies the company’s default mapping (chart of accounts & VAT settings).You can override this by specifying a
ledger_account_idexplicitly.
VAT Rate Codes Reference
vat_ratemust use a supported code.
Code Description Rate FR_200Standard VAT France 20% FR_100Reduced VAT France 10% FR_055Reduced VAT France 5.5% exemptExempt (0%) 0% anyNo specific VAT code — For the full list of supported VAT codes, see the API Reference for Import Supplier Invoice.
Step 4 | Validating the Import
You can verify that the invoice was successfully created:
curl --request GET \
--url https://app.pennylane.com/api/external/v2/supplier_invoices/4431 \
-H "Authorization: Bearer <ACCESS_TOKEN>"✅ Result
{
"id": 4431,
"status": "imported",
"currency_amount": "120.00",
"supplier_name": "ACME Office Supplies"
}Common errors
401 Unauthorized→ Invalid or expired token403 Forbidden→ Missing scope (supplier_invoices:all)422 Unprocessable Entity→ VAT or totals mismatch
Tip: In sandbox, you can safely test imports with fake suppliers and sample amounts.
Step 5 | (Optional) Categorizing the Invoice
Categorization helps analyze expenses by department, cost center, or activity.
1. Get or Create a Category
# List categories
GET /api/external/v2/categories
# Create a new category
POST /api/external/v2/categories
2. Assign the Category to the Invoice
curl --request PUT \
--url https://app.pennylane.com/api/external/v2/supplier_invoices/{invoice_id}/categories \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '[
{ "id": 123, "weight": 1.0 }
]'Note
weightrepresents the allocation percentage (1.0= 100%,0.5= 50%). Multiple categories are supported.
Test in Sandbox or Postman
You can test this workflow safely using your Pennylane Sandbox or the official Postman collection.
- Collection:
Pennylane API v2 → Supplier Invoices → Import - Replace
<ACCESS_TOKEN>with your sandbox token - Use real
supplier_idandledger_account_idfrom your sandbox company
✅ Result
Testing in sandbox ensures your flow works end-to-end before deploying to production.
Common Pitfalls
| Issue | Likely Cause | How to Fix |
|---|---|---|
400 Bad Request | Invalid payload: unexpected field or missing required property | Check field names, required fields, and data types |
401 Unauthorized | Missing or expired token | Refresh token or fix header |
403 Forbidden | Missing scope | Add supplier_invoices:all |
404 File not found | Invalid/expired file_attachment_id | Re-upload via /file_attachments |
422 Entry lines are not balanced | HT/TVA/TTC mismatch | Recalculate totals |
Best Practices
- Validate before import — totals & VAT consistency
- Use appropriate accounts — e.g.,
60xexpenses,4456deductible VAT,401suppliers - Secure tokens — rotate & store safely
- Test in sandbox first — then roll out to production
Duplicate handling
Pennylane automatically prevents duplicates by rejecting supplier invoices whose attached PDF (
file_attachment_id) already exists in the workspace — whether it was imported manually or via API.If you try to re-import the same file, the API returns
422 Unprocessable Entity.
How Pennylane Handles Accounting
When you import a supplier invoice:
- Pennylane automatically creates expense entries in your accounting ledgers.
- The entries appear in your Purchases journal.
- The invoice is visible in Invoicing → Supplier Invoices in your workspace.
Note
Entries are generated according to your company’s chart of accounts and the
ledger_account_idvalues provided in your payload.
Updated about 3 hours ago
