How to Automate Bulk Invoice Creation in MetroERP Using Excel and n8n API Integration?
Introduction
This guide explains how to connect n8n with MetroERP to automate contact and invoice creation using the MetroERP API. It covers API key generation, API documentation, Excel field mapping, n8n workflow configuration, bulk invoice creation, and troubleshooting.
By following this guide, you can upload an Excel file, read the invoice data, and automatically create multiple customer invoices in MetroERP.
1. How to Get API Keys in MetroERP
An API key is used to authenticate requests sent from n8n to MetroERP. It allows n8n to communicate with MetroERP based on the permissions assigned to the key.
Steps to Generate an API Key
1. Open MetroERP and go to
Accounting → Configuration → n8n Integration → API Keys
2. Click Create
3. Enter a clear name (for example: n8n Production )
4. Choose the Company that should own the invoices and contacts
5. Turn on access as needed:
- Contacts — allow contact create/list/update
- Invoices — allow invoice/bill create/list/update
6. Save, then click Generate / Rotate Key
7. Copy the key immediately and store it in a safe place (n8n credentials)
The full key is shown only once.
How to Send the API Key
Every authenticated Contacts or Invoices API request must include one of the following headers.
Option 1: Authorization header
Authorization: Bearer YOUR_API_KEY
Option 2: Metro API key header
X-Metro-Api-Key: YOUR_API_KEY
Replace YOUR_API_KEY with the actual key generated in MetroERP.
API Key Permissions and Access
- No key or incorrect key: The request is rejected as Unauthorized.
- Key without Contacts permission: Contact API requests are blocked.
- Key without Invoices permission: Invoice API requests are blocked.
Security tip: Keep your API key confidential and use HTTPS when accessing MetroERP over the internet.
2. MetroERP API Documentation
2.1 Base URL
The MetroERP API base URL is:
https://YOUR-METRO-URL/api/n8n/v1
Replace YOUR-METRO-URL with the MetroERP address provided by your MetroERP administrator.
Example format:
https://metro.yourcompany.com/api/n8n/v1
2.2 Required Request Headers
For invoice and contact creation or updating, configure the following headers:
- Content-Type: text/plain
- Accept: application/json
- Authorization: Bearer YOUR_API_KEY
Important: The API expects a JSON request body even when the Content-Type is set to text/plain.
2.3 Available API Endpoints
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /health | Check whether the API service is reachable |
| GET | /contacts | List contacts |
| GET | /contacts/{id} | Retrieve a specific contact |
| POST | /contacts | Create a contact |
| PUT / PATCH | /contacts/{id} | Update a contact |
| GET | /invoices | List invoices and bills |
| GET | /invoices/{id} | Retrieve a specific invoice |
| POST | /invoices | Create an invoice or bill |
| PUT / PATCH | /invoices/{id} | Update an invoice |
The /health endpoint does not require an API key. The other endpoints require authentication.
2.4 Health Check
Use the following endpoint to check whether MetroERP is reachable:
GET /api/n8n/v1/health
No API key is required for this health check.
2.5 Contacts API
List Contacts
Endpoint:
GET /api/n8n/v1/contacts?search=&limit=50&offset=0
Available parameters:
- search: Optional filter by contact name, email, or phone.
- limit: Maximum number of records to return. The documented default is 80.
- offset: Pagination offset.
Get a Contact
Endpoint:
GET /api/n8n/v1/contacts/{id}
Replace {id} with the contact's ID.
Create a Contact
Endpoint:
POST /api/n8n/v1/contacts
Supported fields:
| Field | Required | Description |
|---|---|---|
| name | Yes | Contact or company name |
| No | Email address | |
| phone | No | Phone number |
| is_company | No | true or false; defaults to true |
| vat | No | Tax identification number, if used |
| country | No | Country code, for example, SG |
{ "name": "Acme Trading Pte Ltd", "email": "ap@acme.example", "phone": "+65 6000 0000", "is_company": true }
Update a Contact
Endpoint:
PUT /api/n8n/v1/contacts/{id}
Send only the fields that you want to change.2.6 Invoices API
List Invoices
Endpoint:
GET /api/n8n/v1/invoices?type=invoice&status=draft&limit=50
Available parameters:
type: Optional document type, such as invoice, bill, or credit_note.
status: Optional status filter, such as draft or posted.
partner_id: Optional customer or vendor ID.
limit and offset: Pagination controls.
Get an Invoice
Endpoint:
GET /api/n8n/v1/invoices/{id}
Replace {id} with the invoice ID.
Create an Invoice
Endpoint:
POST /api/n8n/v1/invoices
Supported invoice header fields:
| Field | Required | Description |
|---|---|---|
| partner_id or contact.name / partner_name | Yes, one option | Identifies the customer or vendor |
| line_items | Yes | At least one invoice line |
| type | No | Defaults to invoice; also supports bill, credit_note, and bill_credit_note |
| contact.email | No | Helps find or create a contact |
| contact.phone | No | Stored when creating a contact |
| contact.is_company | No | Defaults to true |
| invoice_date | No | Date in YYYY-MM-DD format; defaults to today |
| due_date | No | Invoice due date |
| reference | No | External reference or job number |
| currency | No | Currency code, such as SGD or USD; defaults to company currency |
| post | No | true to post after creation; defaults to false |
Invoice Line Fields
| Field | Required | Description |
|---|---|---|
| description or label | Usually yes | Invoice line description |
| quantity | No | Quantity; defaults to 1 |
| unit_amount | No | Unit price |
| uom | No | Unit of measure name, for example, Units |
| discount_type | No | percent or fixed |
| discount | No | Discount value |
| account_code | No | Income or expense account code |
| product_code / product_id | No | Links a product |
| tax_ids | No | List of tax IDs, for example, [1, 2] |
Example: Create a Customer Invoice
{
"type": "invoice",
"contact": {
"name": "Acme Trading Pte Ltd",
"email": "ap@acme.example",
"phone": "+65 6000 0000",
"is_company": true
},
"invoice_date": "2026-10-07",
"due_date": "2026-11-07",
"reference": "INV-N8N-001",
"currency": "USD",
"post": false,
"line_items": [
{
"description": "Consulting services",
"quantity": 1,
"unit_amount": 500,
"uom": "Units",
"discount_type": "percent",
"discount": 10,
"account_code": "400000",
"product_code": "CONS-01"
}]
}
In this example, the invoice is created as a draft because post is set to false.
Minimal Invoice Example
{
"contact": {
"name": "Acme Trading Pte Ltd"
},
"line_items": [
{
"description": "Consulting services",
"quantity": 1,
"unit_amount": 500
}
]
}Update an Invoice
Endpoint:
PUT /api/n8n/v1/invoices/{id}
Draft invoices can be fully updated. Posted invoices accept only limited changes, such as the reference.
2.7 Example API Request Using cURL
The following example demonstrates how to create an invoice using the MetroERP API.
curl -X POST 'https://YOUR-METRO-URL/api/n8n/v1/invoices' \
-H 'Authorizati
on: Bearer YOUR_API_KEY' \
-H 'Content-Type: text/plain' \
-H 'Accept: application/json' \
--data-raw '{
"contact": {
"name": "Acme Trading Pte Ltd",
"email": "ap@acme.example"
},
"reference": "INV-001",
"currency": "SGD",
"line_items": [
{
"description": "Service",
"quantity": 1,
"unit_amount": 100
}
]
}'Replace the MetroERP URL and API key with the values provided for your environment.
3. Prepare Your Excel File and Map Invoice Fields
Before configuring the n8n workflow, prepare your Excel file using the field names expected by the workflow.
For the simplest workflow described in this guide, use one row per invoice with one line item per row.
3.1 Recommended Excel Columns
Create an Excel spreadsheet with the following column headers:
customer_name, email, phone, invoice_date, due_date, reference, currency, description, quantity, unit_amount, uom, discount_type, discount, account_code, product_code
3.2 Excel Field Mapping
| Excel Column | Used For | MetroERP API Field |
|---|---|---|
| customer_name | Customer name | contact.name |
| Customer email | contact.email | |
| phone | Customer phone | contact.phone |
| invoice_date | Invoice date | invoice_date |
| due_date | Due date | due_date |
| reference | Invoice reference | reference |
| currency | Currency code | currency |
| description | Invoice line description | line_items.description |
| quantity | Line quantity | line_items.quantity |
| unit_amount | Unit price | line_items.unit_amount |
| uom | Unit of measure | line_items.uom |
| discount_type | Discount method | line_items.discount_type |
| discount | Discount value | line_items.discount |
| account_code | Income or expense account | line_items.account_code |
| product_code | Product code | line_items.product_code |
3.3 Excel Preparation Guidelines
Use the exact column names listed above because the workflow refers to these names.
Ensure customer names are populated.
Use valid dates in YYYY-MM-DD format.
Enter numeric values for quantity, unit price, and discount.
Use currency codes configured for the company.
Ensure account codes exist for the relevant company.
Use valid product codes when linking products.
Save the spreadsheet as .xlsx or .csv.
Important: The sample workflow creates one invoice for each input row. If one invoice must contain multiple line items, the workflow needs additional grouping logic to combine those rows into a single invoice.
4. Configure an n8n Workflow to Create Bulk Invoices in MetroERP
You do not need a special MetroERP community node in n8n. A standard HTTP Request node is sufficient and can be used with n8n Cloud or a local n8n installation.
Workflow Overview
Upload Excel → Read Excel Rows → Create Invoices in MetroERP
The workflow reads the Excel data and sends an invoice creation request to MetroERP for each row.
Step 1: Create the Workflow
Open n8n.
Click Add workflow.
Enter a workflow name, for example, Excel → Metro Invoices.
Save the workflow.
Step 2: Add a Trigger for File Upload
For users who need to upload an Excel file, use the On form submission (Form Trigger) node. You can use a Manual Trigger for testing.
Add the On form submission node.
Set the form title to Upload invoices Excel.
Add a field with the following settings:
Type: File
Label: Excel File
Required: Yes
Save the node.
This trigger allows the workflow to receive the Excel file before processing it.
Step 3: Read the Excel Rows
Add an Extract from File or Spreadsheet File node, depending on the nodes available in your n8n version.
Select the appropriate Excel or spreadsheet operation.
Configure the uploaded file as the input.
Execute the node once to test it.
Confirm that the output contains one item per Excel row and that the column names match the expected headers.
The output should include fields such as customer_name, invoice_date, description, quantity, and unit_amount.
Step 4: Map Excel Fields to the Invoice JSON Body
Add an HTTP Request node after the spreadsheet processing node.
Configure the request body in Expression mode using the following mapping:
{{
{
"type": "invoice",
"contact": {
"name": $json.customer_name,
"email": $json.email,
"phone": $json.phone,
"is_company": true
},
"invoice_date": $json.invoice_date,
"due_date": $json.due_date,
"reference": $json.reference,
"currency": $json.currency,
"post": false,
"line_items": [
{
"description": $json.description,
"quantity": $json.quantity,
"unit_amount": $json.unit_amount,
"uom": $json.uom,
"discount_type": $json.discount_type || "percent",
"discount": $json.discount,
"account_code": $json.account_code,
"product_code": $json.product_code
}
]
}
}}This mapping transfers the Excel values into the appropriate MetroERP invoice fields.
Field mapping reference:
customer_name → contact.name
email → contact.email
phone → contact.phone
invoice_date → invoice_date
due_date → due_date
reference → reference
currency → currency
description → line_items.description
quantity → line_items.quantity
unit_amount → line_items.unit_amount
uom → line_items.uom
discount_type → line_items.discount_type
discount → line_items.discount
account_code → line_items.account_code
product_code → line_items.product_code
The expression defaults discount_type to percent when the Excel value is empty or otherwise evaluates as falsy.
Step 5: Configure the HTTP Request Node
Set up the HTTP Request node as follows:
| Setting | Value |
|---|---|
| Method | POST |
| URL | https://YOUR-METRO-URL/api/n8n/v1/invoices |
| Authorization header | Authorization: Bearer YOUR_API_KEY |
| Content-Type header | Content-Type: text/plain |
| Accept header | Accept: application/json |
| Body | JSON expression configured in Step 4 |
Replace YOUR-METRO-URL and YOUR_API_KEY with the actual values for your MetroERP environment.
Ensure the request sends the JSON body in the format expected by the API.
How bulk invoice creation works: The HTTP Request node runs for each input item. If the spreadsheet node outputs multiple rows, n8n sends multiple invoice creation requests to MetroERP.
Step 6: Import cURL into n8n Cloud for Faster Setup
You can configure the HTTP Request node by importing a cURL command in n8n Cloud.
Add an HTTP Request node.
Open Import cURL.
Paste the following command.
Replace YOUR-METRO-URL and YOUR_API_KEY.
Connect the spreadsheet processing node to the HTTP Request node.
Save and run the workflow.
Example cURL command:
curl -X POST 'https://YOUR-METRO-URL/api/n8n/v1/invoices' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: text/plain' \
-H 'Accept: application/json' \
--data-raw '{
"type": "invoice",
"contact": {
"name": "{{ $json.customer_name }}",
"email": "{{ $json.email }}",
"phone": "{{ $json.phone }}",
"is_company": true
},
"invoice_date": "{{ $json.invoice_date }}",
"due_date": "{{ $json.due_date }}",
"reference": "{{ $json.reference }}",
"currency": "{{ $json.currency }}",
"post": false,
"line_items": [
{
"description": "{{ $json.description }}",
"quantity": {{ $json.quantity }},
"unit_amount": {{ $json.unit_amount }},
"uom": "{{ $json.uom }}",
"discount_type": "{{ $json.discount_type }}",
"discount": {{ $json.discount }},
"account_code": "{{ $json.account_code }}",
"product_code": "{{ $json.product_code }}"
}
]
}'n8n Cloud note: MetroERP must be reachable from the internet through a public HTTPS URL. n8n Cloud cannot directly access a MetroERP server running only on a private localhost address.
Step 7: Run the Workflow and Verify Invoices in MetroERP
Save the completed workflow.
Execute the workflow and upload your prepared Excel file.
Check the execution results in n8n.
Open MetroERP.
Navigate to Accounting → Customers → Invoices.
Search for the created invoices using the reference values from your Excel file.
Verify the customer, invoice date, due date, currency, line description, quantity, unit price, and other relevant fields.
If post is set to false, the invoices remain in Draft until they are posted.
Always test the workflow with one or two Excel rows before processing the complete file.
5. Quick Checklist Before Running the Workflow
Use this checklist before uploading a large Excel file.
API key generated in MetroERP and copied securely into n8n.
Required Contacts and Invoices permissions enabled.
MetroERP URL reachable from n8n.
Excel column names match the workflow mappings.
Customer names and required invoice line descriptions are populated.
Workflow connected in this order: Upload → Read Excel → HTTP Request.
JSON body maps the correct $json fields.
Headers configured with the API key, Content-Type: text/plain, and Accept: application/json.
Currency and account codes are valid for the company.
Test completed with one or two rows.
Created invoices verified in MetroERP.
6. Common Issues and Troubleshooting
| Issue | What to Check |
|---|---|
| Unauthorized | Check the API key and Authorization header. |
| Forbidden | Enable the required Invoices or Contacts permission on the API key. |
| Cannot connect from n8n Cloud | Use a publicly reachable MetroERP HTTPS URL. |
| Unexpected error or JSON-RPC error | Verify that Content-Type: text/plain is configured as documented. |
| Empty customer name | Ensure the Excel header is exactly customer_name and the row contains a value. |
| Currency error | Use a valid currency code configured in MetroERP. |
| Account code error | Verify that the account code exists for the selected company. |
If the problem persists, check the n8n execution details and the API response to identify which request or field caused the failure.
7. Need Help?
Contact your MetroERP administrator for assistance with:
Obtaining the MetroERP base URL.
Getting access to API key generation.
Configuring company access and API permissions.
Verifying currency and account code setup.
Investigating API errors or connectivity issues.
Conclusion
By following this guide, you can configure n8n to read invoice information from an Excel file and create invoices automatically in MetroERP through the API.
For reliable processing, verify your Excel data, test the workflow with a small number of rows, and check the created invoices in MetroERP before running the full batch.
Document: Customer Guide — MetroERP Automation with n8n
Topic: API Keys, REST API, Excel Field Mapping, and Bulk Invoice Creation