Automating e-archive invoices on your online store
The steps needed to issue an invoice and get it to the customer the moment an order comes in: the right document type, choosing an integrator and connecting it to your order flow.
As orders start to grow on an e-commerce site, issuing invoices one by one quickly becomes a bottleneck. The good news: set up correctly, the invoice can be issued the moment a payment is confirmed and land in your customer's inbox on its own.
1. Be clear about which document you need to issue
The rule in Turkey is simple: if the buyer is registered for e-invoicing, you issue an e-invoice; otherwise you issue an e-archive invoice. Almost all of your sales to individual customers will be e-archive. When a business customer enters a tax number, you first check their registration status.
As of 2026, electronic invoicing has become the general rule. The date and revenue threshold from which it applies to you depends on your company type and bookkeeping method.
2. Choose a private integrator
The Revenue Administration's free e-Archive Portal works for low volumes, but it offers no API for automation. To issue invoices from orders automatically, you need a private integrator's API. When choosing one, look for:
- A documented REST API and a test (sandbox) environment
- The ability to check e-invoice registration
- The invoice PDF and number returned in the response
- Credit-based or per-document pricing that fits your volume
3. Build the order-to-invoice flow
The flow itself has five steps:
- An event is triggered when the payment is confirmed.
- If the customer entered a tax number, their registration is checked.
- Depending on the result, an e-invoice or e-archive request is sent to the integrator.
- The returned invoice number and PDF link are saved on the order.
- The customer receives an order confirmation email with the invoice.
If you're on Medusa v2, you can build this flow with a subscriber:
// src/subscribers/order-invoice.ts (simplified example)
import type { SubscriberArgs, SubscriberConfig } from "@medusajs/framework"
import { Modules } from "@medusajs/framework/utils"
import { createInvoice } from "../lib/e-invoice" // integrator client
export default async function orderInvoice({ event, container }: SubscriberArgs<{ id: string }>) {
const orders = container.resolve(Modules.ORDER)
const order = await orders.retrieveOrder(event.data.id, { relations: ["items", "billing_address"] })
const invoice = await createInvoice(order) // e-invoice or e-archive is decided here
await orders.updateOrders(order.id, {
metadata: { ...order.metadata, invoice_no: invoice.number, invoice_pdf: invoice.pdfUrl },
})
}
export const config: SubscriberConfig = { event: "order.placed" }
4. Don't forget errors and refunds
The integrator's API may not always respond right away. Queueing invoice requests and retrying failed ones keeps orders from ending up without an invoice. For refunds and cancellations, you'll also need a branch in the same flow so the matching document is created automatically.
Conclusion
Set up correctly, invoicing becomes an invisible part of your operations. You focus on selling while invoices are issued in the background.