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

MethodEndpointPurpose
GET/healthCheck whether the API service is reachable
GET/contactsList contacts
GET/contacts/{id}Retrieve a specific contact
POST/contactsCreate a contact
PUT / PATCH/contacts/{id}Update a contact
GET/invoicesList invoices and bills
GET/invoices/{id}Retrieve a specific invoice
POST/invoicesCreate 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:

FieldRequiredDescription
nameYesContact or company name
emailNoEmail address
phoneNoPhone number
is_companyNotrue or false; defaults to true
vatNoTax identification number, if used
countryNoCountry code, for example, SG
Example request body:
{ "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:

FieldRequiredDescription
partner_id or contact.name / partner_nameYes, one optionIdentifies the customer or vendor
line_itemsYesAt least one invoice line
typeNoDefaults to invoice; also supports bill, credit_note, and bill_credit_note
contact.emailNoHelps find or create a contact
contact.phoneNoStored when creating a contact
contact.is_companyNoDefaults to true
invoice_dateNoDate in YYYY-MM-DD format; defaults to today
due_dateNoInvoice due date
referenceNoExternal reference or job number
currencyNoCurrency code, such as SGD or USD; defaults to company currency
postNotrue to post after creation; defaults to false
When a different currency is selected, MetroERP uses the exchange rate for the invoice date.

Invoice Line Fields

FieldRequiredDescription
description or labelUsually yesInvoice line description
quantityNoQuantity; defaults to 1
unit_amountNoUnit price
uomNoUnit of measure name, for example, Units
discount_typeNopercent or fixed
discountNoDiscount value
account_codeNoIncome or expense account code
product_code / product_idNoLinks a product
tax_idsNoList of tax IDs, for example, [1, 2]
Important: Do not send calculated totals such as price_subtotal. MetroERP calculates these values.

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 ColumnUsed ForMetroERP API Field
customer_nameCustomer namecontact.name
emailCustomer emailcontact.email
phoneCustomer phonecontact.phone
invoice_dateInvoice dateinvoice_date
due_dateDue datedue_date
referenceInvoice referencereference
currencyCurrency codecurrency
descriptionInvoice line descriptionline_items.description
quantityLine quantityline_items.quantity
unit_amountUnit priceline_items.unit_amount
uomUnit of measureline_items.uom
discount_typeDiscount methodline_items.discount_type
discountDiscount valueline_items.discount
account_codeIncome or expense accountline_items.account_code
product_codeProduct codeline_items.product_code

3.3 Excel Preparation Guidelines

  1. Use the exact column names listed above because the workflow refers to these names.

  2. Ensure customer names are populated.

  3. Use valid dates in YYYY-MM-DD format.

  4. Enter numeric values for quantity, unit price, and discount.

  5. Use currency codes configured for the company.

  6. Ensure account codes exist for the relevant company.

  7. Use valid product codes when linking products.

  8. 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

  1. Open n8n.

  2. Click Add workflow.

  3. Enter a workflow name, for example, Excel → Metro Invoices.

  4. 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.

  1. Add the On form submission node.

  2. Set the form title to Upload invoices Excel.

  3. Add a field with the following settings:

    • Type: File

    • Label: Excel File

    • Required: Yes

  4. Save the node.

This trigger allows the workflow to receive the Excel file before processing it.

Step 3: Read the Excel Rows

  1. Add an Extract from File or Spreadsheet File node, depending on the nodes available in your n8n version.

  2. Select the appropriate Excel or spreadsheet operation.

  3. Configure the uploaded file as the input.

  4. Execute the node once to test it.

  5. 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:

SettingValue
MethodPOST
URLhttps://YOUR-METRO-URL/api/n8n/v1/invoices
Authorization headerAuthorization: Bearer YOUR_API_KEY
Content-Type headerContent-Type: text/plain
Accept headerAccept: application/json
BodyJSON 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.

  1. Add an HTTP Request node.

  2. Open Import cURL.

  3. Paste the following command.

  4. Replace YOUR-METRO-URL and YOUR_API_KEY.

  5. Connect the spreadsheet processing node to the HTTP Request node.

  6. 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

  1. Save the completed workflow.

  2. Execute the workflow and upload your prepared Excel file.

  3. Check the execution results in n8n.

  4. Open MetroERP.

  5. Navigate to Accounting → Customers → Invoices.

  6. Search for the created invoices using the reference values from your Excel file.

  7. Verify the customer, invoice date, due date, currency, line description, quantity, unit price, and other relevant fields.

  8. 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

IssueWhat to Check
UnauthorizedCheck the API key and Authorization header.
ForbiddenEnable the required Invoices or Contacts permission on the API key.
Cannot connect from n8n CloudUse a publicly reachable MetroERP HTTPS URL.
Unexpected error or JSON-RPC errorVerify that Content-Type: text/plain is configured as documented.
Empty customer nameEnsure the Excel header is exactly customer_name and the row contains a value.
Currency errorUse a valid currency code configured in MetroERP.
Account code errorVerify 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