> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.mercoa.com/embedded-ap-ar/guides/accounts-payable/invoices/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.mercoa.com/_mcp/server. ## [API Reference](/api-reference/invoice/create) # Lifecycle of an invoice The invoice lifecycle is as follows: ![Invoice Lifecycle](/_fern-img/7d05ebe8201821d69477015bcb28cc5c1ee36bba67becad47a53785e5fe8c712.webp) This guide goes through the minimum required data to get an invoice through the complete lifecycle. If you are using the Mercoa embed or React component, all these steps are automatically handled for you. # 1. Creating a Draft If an invoice is [created](/api-reference/invoice/create) and saved as draft, or if it comes in through the [email inbox](/accounts-payable/email-inbox) it's in the `DRAFT` state. ## What needs to be set to get in this state ### CreatorEntityId The Creator Entity is the [entity](/common-concepts/entities) that created the invoice. ### PayerId The payer is the [entity](/common-concepts/entities) that's paying the invoice. ### Request POST [https://api.mercoa.com/invoice](https://api.mercoa.com/invoice) **`CreateDraftInvoice`** ```curl CreateDraftInvoice curl -X POST https://api.mercoa.com/invoice \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "status": "DRAFT", "payerId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", "creatorEntityId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c" }' ``` **`CreateDraftInvoice`** ```python CreateDraftInvoice import requests url = "https://api.mercoa.com/invoice" payload = { "status": "DRAFT", "payerId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", "creatorEntityId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` **`CreateDraftInvoice`** ```typescript CreateDraftInvoice import { MercoaClient } from "@mercoa/javascript"; const client = new MercoaClient({ token: "YOUR_TOKEN" }); await client.invoice.create({ status: "DRAFT", payerId: "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", creatorEntityId: "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c" }); ``` **`CreateDraftInvoice`** ```go CreateDraftInvoice package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://api.mercoa.com/invoice" payload := strings.NewReader("{\n \"status\": \"DRAFT\",\n \"payerId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\",\n \"creatorEntityId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) } ``` **`CreateDraftInvoice`** ```ruby CreateDraftInvoice require 'uri' require 'net/http' url = URI("https://api.mercoa.com/invoice") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"status\": \"DRAFT\",\n \"payerId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\",\n \"creatorEntityId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\"\n}" response = http.request(request) puts response.read_body ``` **`CreateDraftInvoice`** ```java CreateDraftInvoice import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.post("https://api.mercoa.com/invoice") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"status\": \"DRAFT\",\n \"payerId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\",\n \"creatorEntityId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\"\n}") .asString(); ``` **`CreateDraftInvoice`** ```php CreateDraftInvoice request('POST', 'https://api.mercoa.com/invoice', [ 'body' => '{ "status": "DRAFT", "payerId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", "creatorEntityId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c" }', 'headers' => [ 'Authorization' => 'Bearer ', 'Content-Type' => 'application/json', ], ]); echo $response->getBody(); ``` **`CreateDraftInvoice`** ```csharp CreateDraftInvoice using RestSharp; var client = new RestClient("https://api.mercoa.com/invoice"); var request = new RestRequest(Method.POST); request.AddHeader("Authorization", "Bearer "); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "{\n \"status\": \"DRAFT\",\n \"payerId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\",\n \"creatorEntityId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\"\n}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` **`CreateDraftInvoice`** ```swift CreateDraftInvoice import Foundation let headers = [ "Authorization": "Bearer ", "Content-Type": "application/json" ] let parameters = [ "status": "DRAFT", "payerId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", "creatorEntityId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c" ] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "https://api.mercoa.com/invoice")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "POST" request.allHTTPHeaderFields = headers request.httpBody = postData as Data let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error as Any) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume() ``` All other information is optional at this point, and the invoice can be updated at any time with partial information as you get it. # 2. Getting ready for approval An invoice that has all information required to be approved can be moved to the `NEW` state. ## What needs to be set to get in this state ### Vendor ID The vendor is the [Entity](/common-concepts/entities) that's receiving the payment for the invoice. The vendor needs to be [created](/api-reference/entity/create) and have a valid profile. ### Amount and Currency The `amount` is the total amount of the invoice. This is the amount that's paid to the vendor. The `currency` is the currency that the invoice is in, e.g. `USD`. ### Invoice Date The `invoiceDate` is the date that the invoice was issued. ### Due Date The `dueDate` is the date that the invoice is due. ### Payment Source ID This is the [payment method](/common-concepts/payment-methods/overview) for the payer (funding source) #### Create New ### Request POST [https://api.mercoa.com/invoice](https://api.mercoa.com/invoice) **`CreateNewInvoice`** ```curl CreateNewInvoice curl -X POST https://api.mercoa.com/invoice \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "status": "NEW", "payerId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", "creatorEntityId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", "vendorId": "ent_21661ac1-a2a8-4465-a6c0-64474ba8181d", "currency": "USD", "amount": 100, "invoiceDate": "2021-01-01T00:00:00Z", "dueDate": "2021-01-31T00:00:00Z", "paymentSourceId": "pm_4794d597-70dc-4fec-b6ec-c5988e759769", "paymentDestinationId": "pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18", "deductionDate": "2021-01-29T00:00:00Z" }' ``` **`CreateNewInvoice`** ```python CreateNewInvoice import requests url = "https://api.mercoa.com/invoice" payload = { "status": "NEW", "payerId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", "creatorEntityId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", "vendorId": "ent_21661ac1-a2a8-4465-a6c0-64474ba8181d", "currency": "USD", "amount": 100, "invoiceDate": "2021-01-01T00:00:00Z", "dueDate": "2021-01-31T00:00:00Z", "paymentSourceId": "pm_4794d597-70dc-4fec-b6ec-c5988e759769", "paymentDestinationId": "pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18", "deductionDate": "2021-01-29T00:00:00Z" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` **`CreateNewInvoice`** ```typescript CreateNewInvoice import { MercoaClient } from "@mercoa/javascript"; const client = new MercoaClient({ token: "YOUR_TOKEN" }); await client.invoice.create({ status: "NEW", payerId: "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", creatorEntityId: "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", vendorId: "ent_21661ac1-a2a8-4465-a6c0-64474ba8181d", currency: "USD", amount: 100, invoiceDate: new Date("2021-01-01T00:00:00.000Z"), dueDate: new Date("2021-01-31T00:00:00.000Z"), paymentSourceId: "pm_4794d597-70dc-4fec-b6ec-c5988e759769", paymentDestinationId: "pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18", deductionDate: new Date("2021-01-29T00:00:00.000Z") }); ``` **`CreateNewInvoice`** ```go CreateNewInvoice package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://api.mercoa.com/invoice" payload := strings.NewReader("{\n \"status\": \"NEW\",\n \"payerId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\",\n \"creatorEntityId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\",\n \"vendorId\": \"ent_21661ac1-a2a8-4465-a6c0-64474ba8181d\",\n \"currency\": \"USD\",\n \"amount\": 100,\n \"invoiceDate\": \"2021-01-01T00:00:00Z\",\n \"dueDate\": \"2021-01-31T00:00:00Z\",\n \"paymentSourceId\": \"pm_4794d597-70dc-4fec-b6ec-c5988e759769\",\n \"paymentDestinationId\": \"pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18\",\n \"deductionDate\": \"2021-01-29T00:00:00Z\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) } ``` **`CreateNewInvoice`** ```ruby CreateNewInvoice require 'uri' require 'net/http' url = URI("https://api.mercoa.com/invoice") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"status\": \"NEW\",\n \"payerId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\",\n \"creatorEntityId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\",\n \"vendorId\": \"ent_21661ac1-a2a8-4465-a6c0-64474ba8181d\",\n \"currency\": \"USD\",\n \"amount\": 100,\n \"invoiceDate\": \"2021-01-01T00:00:00Z\",\n \"dueDate\": \"2021-01-31T00:00:00Z\",\n \"paymentSourceId\": \"pm_4794d597-70dc-4fec-b6ec-c5988e759769\",\n \"paymentDestinationId\": \"pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18\",\n \"deductionDate\": \"2021-01-29T00:00:00Z\"\n}" response = http.request(request) puts response.read_body ``` **`CreateNewInvoice`** ```java CreateNewInvoice import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.post("https://api.mercoa.com/invoice") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"status\": \"NEW\",\n \"payerId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\",\n \"creatorEntityId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\",\n \"vendorId\": \"ent_21661ac1-a2a8-4465-a6c0-64474ba8181d\",\n \"currency\": \"USD\",\n \"amount\": 100,\n \"invoiceDate\": \"2021-01-01T00:00:00Z\",\n \"dueDate\": \"2021-01-31T00:00:00Z\",\n \"paymentSourceId\": \"pm_4794d597-70dc-4fec-b6ec-c5988e759769\",\n \"paymentDestinationId\": \"pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18\",\n \"deductionDate\": \"2021-01-29T00:00:00Z\"\n}") .asString(); ``` **`CreateNewInvoice`** ```php CreateNewInvoice request('POST', 'https://api.mercoa.com/invoice', [ 'body' => '{ "status": "NEW", "payerId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", "creatorEntityId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", "vendorId": "ent_21661ac1-a2a8-4465-a6c0-64474ba8181d", "currency": "USD", "amount": 100, "invoiceDate": "2021-01-01T00:00:00Z", "dueDate": "2021-01-31T00:00:00Z", "paymentSourceId": "pm_4794d597-70dc-4fec-b6ec-c5988e759769", "paymentDestinationId": "pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18", "deductionDate": "2021-01-29T00:00:00Z" }', 'headers' => [ 'Authorization' => 'Bearer ', 'Content-Type' => 'application/json', ], ]); echo $response->getBody(); ``` **`CreateNewInvoice`** ```csharp CreateNewInvoice using RestSharp; var client = new RestClient("https://api.mercoa.com/invoice"); var request = new RestRequest(Method.POST); request.AddHeader("Authorization", "Bearer "); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "{\n \"status\": \"NEW\",\n \"payerId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\",\n \"creatorEntityId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\",\n \"vendorId\": \"ent_21661ac1-a2a8-4465-a6c0-64474ba8181d\",\n \"currency\": \"USD\",\n \"amount\": 100,\n \"invoiceDate\": \"2021-01-01T00:00:00Z\",\n \"dueDate\": \"2021-01-31T00:00:00Z\",\n \"paymentSourceId\": \"pm_4794d597-70dc-4fec-b6ec-c5988e759769\",\n \"paymentDestinationId\": \"pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18\",\n \"deductionDate\": \"2021-01-29T00:00:00Z\"\n}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` **`CreateNewInvoice`** ```swift CreateNewInvoice import Foundation let headers = [ "Authorization": "Bearer ", "Content-Type": "application/json" ] let parameters = [ "status": "NEW", "payerId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", "creatorEntityId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", "vendorId": "ent_21661ac1-a2a8-4465-a6c0-64474ba8181d", "currency": "USD", "amount": 100, "invoiceDate": "2021-01-01T00:00:00Z", "dueDate": "2021-01-31T00:00:00Z", "paymentSourceId": "pm_4794d597-70dc-4fec-b6ec-c5988e759769", "paymentDestinationId": "pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18", "deductionDate": "2021-01-29T00:00:00Z" ] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "https://api.mercoa.com/invoice")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "POST" request.allHTTPHeaderFields = headers request.httpBody = postData as Data let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error as Any) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume() ``` #### Update Draft to New ### Request POST [https://api.mercoa.com/invoice/\{invoiceId}](https://api.mercoa.com/invoice/\{invoiceId}) **`DraftToNew`** ```curl DraftToNew curl -X POST https://api.mercoa.com/invoice/in_26e7b5d3-a739-4b23-9ad9-6aaa085f47a9 \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "amount": 100, "currency": "USD", "dueDate": "2021-01-31T00:00:00Z", "invoiceDate": "2021-01-01T00:00:00Z", "paymentSourceId": "pm_4794d597-70dc-4fec-b6ec-c5988e759769", "status": "NEW", "vendorId": "ent_21661ac1-a2a8-4465-a6c0-64474ba8181d" }' ``` **`DraftToNew`** ```python DraftToNew import requests url = "https://api.mercoa.com/invoice/in_26e7b5d3-a739-4b23-9ad9-6aaa085f47a9" payload = { "amount": 100, "currency": "USD", "dueDate": "2021-01-31T00:00:00Z", "invoiceDate": "2021-01-01T00:00:00Z", "paymentSourceId": "pm_4794d597-70dc-4fec-b6ec-c5988e759769", "status": "NEW", "vendorId": "ent_21661ac1-a2a8-4465-a6c0-64474ba8181d" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` **`DraftToNew`** ```typescript DraftToNew import { MercoaClient } from "@mercoa/javascript"; const client = new MercoaClient({ token: "YOUR_TOKEN" }); await client.invoice.update("in_26e7b5d3-a739-4b23-9ad9-6aaa085f47a9", { status: "NEW", vendorId: "ent_21661ac1-a2a8-4465-a6c0-64474ba8181d", currency: "USD", amount: 100, invoiceDate: new Date("2021-01-01T00:00:00.000Z"), dueDate: new Date("2021-01-31T00:00:00.000Z"), paymentSourceId: "pm_4794d597-70dc-4fec-b6ec-c5988e759769" }); ``` **`DraftToNew`** ```go DraftToNew package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://api.mercoa.com/invoice/in_26e7b5d3-a739-4b23-9ad9-6aaa085f47a9" payload := strings.NewReader("{\n \"amount\": 100,\n \"currency\": \"USD\",\n \"dueDate\": \"2021-01-31T00:00:00Z\",\n \"invoiceDate\": \"2021-01-01T00:00:00Z\",\n \"paymentSourceId\": \"pm_4794d597-70dc-4fec-b6ec-c5988e759769\",\n \"status\": \"NEW\",\n \"vendorId\": \"ent_21661ac1-a2a8-4465-a6c0-64474ba8181d\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) } ``` **`DraftToNew`** ```ruby DraftToNew require 'uri' require 'net/http' url = URI("https://api.mercoa.com/invoice/in_26e7b5d3-a739-4b23-9ad9-6aaa085f47a9") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"amount\": 100,\n \"currency\": \"USD\",\n \"dueDate\": \"2021-01-31T00:00:00Z\",\n \"invoiceDate\": \"2021-01-01T00:00:00Z\",\n \"paymentSourceId\": \"pm_4794d597-70dc-4fec-b6ec-c5988e759769\",\n \"status\": \"NEW\",\n \"vendorId\": \"ent_21661ac1-a2a8-4465-a6c0-64474ba8181d\"\n}" response = http.request(request) puts response.read_body ``` **`DraftToNew`** ```java DraftToNew import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.post("https://api.mercoa.com/invoice/in_26e7b5d3-a739-4b23-9ad9-6aaa085f47a9") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"amount\": 100,\n \"currency\": \"USD\",\n \"dueDate\": \"2021-01-31T00:00:00Z\",\n \"invoiceDate\": \"2021-01-01T00:00:00Z\",\n \"paymentSourceId\": \"pm_4794d597-70dc-4fec-b6ec-c5988e759769\",\n \"status\": \"NEW\",\n \"vendorId\": \"ent_21661ac1-a2a8-4465-a6c0-64474ba8181d\"\n}") .asString(); ``` **`DraftToNew`** ```php DraftToNew request('POST', 'https://api.mercoa.com/invoice/in_26e7b5d3-a739-4b23-9ad9-6aaa085f47a9', [ 'body' => '{ "amount": 100, "currency": "USD", "dueDate": "2021-01-31T00:00:00Z", "invoiceDate": "2021-01-01T00:00:00Z", "paymentSourceId": "pm_4794d597-70dc-4fec-b6ec-c5988e759769", "status": "NEW", "vendorId": "ent_21661ac1-a2a8-4465-a6c0-64474ba8181d" }', 'headers' => [ 'Authorization' => 'Bearer ', 'Content-Type' => 'application/json', ], ]); echo $response->getBody(); ``` **`DraftToNew`** ```csharp DraftToNew using RestSharp; var client = new RestClient("https://api.mercoa.com/invoice/in_26e7b5d3-a739-4b23-9ad9-6aaa085f47a9"); var request = new RestRequest(Method.POST); request.AddHeader("Authorization", "Bearer "); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "{\n \"amount\": 100,\n \"currency\": \"USD\",\n \"dueDate\": \"2021-01-31T00:00:00Z\",\n \"invoiceDate\": \"2021-01-01T00:00:00Z\",\n \"paymentSourceId\": \"pm_4794d597-70dc-4fec-b6ec-c5988e759769\",\n \"status\": \"NEW\",\n \"vendorId\": \"ent_21661ac1-a2a8-4465-a6c0-64474ba8181d\"\n}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` **`DraftToNew`** ```swift DraftToNew import Foundation let headers = [ "Authorization": "Bearer ", "Content-Type": "application/json" ] let parameters = [ "amount": 100, "currency": "USD", "dueDate": "2021-01-31T00:00:00Z", "invoiceDate": "2021-01-01T00:00:00Z", "paymentSourceId": "pm_4794d597-70dc-4fec-b6ec-c5988e759769", "status": "NEW", "vendorId": "ent_21661ac1-a2a8-4465-a6c0-64474ba8181d" ] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "https://api.mercoa.com/invoice/in_26e7b5d3-a739-4b23-9ad9-6aaa085f47a9")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "POST" request.allHTTPHeaderFields = headers request.httpBody = postData as Data let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error as Any) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume() ``` Once an invoice is in the `NEW` state, the `amount`, `currency`, `dueDate`, `payerId` and `vendorId` **can't** be changed. # 3. Getting approvals If the entity has an [approval policy](/accounts-payable/approval-policies) set, the invoice needs to be approved by all relevant parties to move to the `APPROVED` state. If the entity does *NOT* have an [approval policy](/accounts-payable/approval-policies) set, the invoice automatically moves into the `APPROVED` state and isn't in the `NEW` state. When the invoice is created, a snapshot of the approval policy is saved to the invoice. This means that any changes to the policy in the future don't reflect on previously created invoices. A list of `approvers` is created on the invoice. An `approver` can be an individual [entity user](/common-concepts/entity-users) or a list of roles. ```ts // Example Approvers list on an invoice { ... approvers: [{ roles: ['approver', 'controller'], action: 'NONE' },{ userId: 'user_123456', action: 'NONE' }] } ``` If an `approver` is a specific user, only that user can fill that approval. Otherwise, any user with an appropriate role can fill an approval. In this example, any user with the role `approver` or `controller` can approve as the first approver, but only `user_123456` can be the second approver. A user can only fill one approval, and approver order is not enforced. If roles are provided, you can update the approvers list by providing a `userId` for a user that's in the appropriate role. Once the `userId` is set, only that user can approve the invoice, and it can't be changed. To add an approval to the invoice, use the [approve](/api-reference/invoice/approval) endpoint. You can pass in an optional `text` field if the user wants to add a comment with their approval. Once all approvals are complete, the invoice automatically moves to the `APPROVED` status. If the invoice already has a `deductionDate` set, it moves to the `SCHEDULED` state. Approvals and Rejections create a [comment](/api-reference/invoice/comment) on the invoice. You can use this to show a list of comments and approvals, as the comments have the approver details as part of the response. # 4. Scheduling the payment Once all approvers have approved the invoice, you can schedule the payment. ## What needs to be set to get in this state ### paymentDestinationId This is the [payment method](/common-concepts/payment-methods/overview) for the vendor (disbursement method). ### Deduction Date This is the date funds are triggered to be moved. #### Create Scheduled ### Request POST [https://api.mercoa.com/invoice](https://api.mercoa.com/invoice) **`CreateScheduledInvoice`** ```curl CreateScheduledInvoice curl -X POST https://api.mercoa.com/invoice \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "status": "SCHEDULED", "payerId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", "creatorEntityId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", "vendorId": "ent_21661ac1-a2a8-4465-a6c0-64474ba8181d", "currency": "USD", "amount": 100, "invoiceDate": "2021-01-01T00:00:00Z", "dueDate": "2021-01-31T00:00:00Z", "paymentSourceId": "pm_4794d597-70dc-4fec-b6ec-c5988e759769", "paymentDestinationId": "pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18", "deductionDate": "2021-01-29T00:00:00Z" }' ``` **`CreateScheduledInvoice`** ```python CreateScheduledInvoice import requests url = "https://api.mercoa.com/invoice" payload = { "status": "SCHEDULED", "payerId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", "creatorEntityId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", "vendorId": "ent_21661ac1-a2a8-4465-a6c0-64474ba8181d", "currency": "USD", "amount": 100, "invoiceDate": "2021-01-01T00:00:00Z", "dueDate": "2021-01-31T00:00:00Z", "paymentSourceId": "pm_4794d597-70dc-4fec-b6ec-c5988e759769", "paymentDestinationId": "pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18", "deductionDate": "2021-01-29T00:00:00Z" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` **`CreateScheduledInvoice`** ```typescript CreateScheduledInvoice import { MercoaClient } from "@mercoa/javascript"; const client = new MercoaClient({ token: "YOUR_TOKEN" }); await client.invoice.create({ status: "SCHEDULED", payerId: "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", creatorEntityId: "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", vendorId: "ent_21661ac1-a2a8-4465-a6c0-64474ba8181d", currency: "USD", amount: 100, invoiceDate: new Date("2021-01-01T00:00:00.000Z"), dueDate: new Date("2021-01-31T00:00:00.000Z"), paymentSourceId: "pm_4794d597-70dc-4fec-b6ec-c5988e759769", paymentDestinationId: "pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18", deductionDate: new Date("2021-01-29T00:00:00.000Z") }); ``` **`CreateScheduledInvoice`** ```go CreateScheduledInvoice package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://api.mercoa.com/invoice" payload := strings.NewReader("{\n \"status\": \"SCHEDULED\",\n \"payerId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\",\n \"creatorEntityId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\",\n \"vendorId\": \"ent_21661ac1-a2a8-4465-a6c0-64474ba8181d\",\n \"currency\": \"USD\",\n \"amount\": 100,\n \"invoiceDate\": \"2021-01-01T00:00:00Z\",\n \"dueDate\": \"2021-01-31T00:00:00Z\",\n \"paymentSourceId\": \"pm_4794d597-70dc-4fec-b6ec-c5988e759769\",\n \"paymentDestinationId\": \"pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18\",\n \"deductionDate\": \"2021-01-29T00:00:00Z\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) } ``` **`CreateScheduledInvoice`** ```ruby CreateScheduledInvoice require 'uri' require 'net/http' url = URI("https://api.mercoa.com/invoice") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"status\": \"SCHEDULED\",\n \"payerId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\",\n \"creatorEntityId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\",\n \"vendorId\": \"ent_21661ac1-a2a8-4465-a6c0-64474ba8181d\",\n \"currency\": \"USD\",\n \"amount\": 100,\n \"invoiceDate\": \"2021-01-01T00:00:00Z\",\n \"dueDate\": \"2021-01-31T00:00:00Z\",\n \"paymentSourceId\": \"pm_4794d597-70dc-4fec-b6ec-c5988e759769\",\n \"paymentDestinationId\": \"pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18\",\n \"deductionDate\": \"2021-01-29T00:00:00Z\"\n}" response = http.request(request) puts response.read_body ``` **`CreateScheduledInvoice`** ```java CreateScheduledInvoice import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.post("https://api.mercoa.com/invoice") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"status\": \"SCHEDULED\",\n \"payerId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\",\n \"creatorEntityId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\",\n \"vendorId\": \"ent_21661ac1-a2a8-4465-a6c0-64474ba8181d\",\n \"currency\": \"USD\",\n \"amount\": 100,\n \"invoiceDate\": \"2021-01-01T00:00:00Z\",\n \"dueDate\": \"2021-01-31T00:00:00Z\",\n \"paymentSourceId\": \"pm_4794d597-70dc-4fec-b6ec-c5988e759769\",\n \"paymentDestinationId\": \"pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18\",\n \"deductionDate\": \"2021-01-29T00:00:00Z\"\n}") .asString(); ``` **`CreateScheduledInvoice`** ```php CreateScheduledInvoice request('POST', 'https://api.mercoa.com/invoice', [ 'body' => '{ "status": "SCHEDULED", "payerId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", "creatorEntityId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", "vendorId": "ent_21661ac1-a2a8-4465-a6c0-64474ba8181d", "currency": "USD", "amount": 100, "invoiceDate": "2021-01-01T00:00:00Z", "dueDate": "2021-01-31T00:00:00Z", "paymentSourceId": "pm_4794d597-70dc-4fec-b6ec-c5988e759769", "paymentDestinationId": "pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18", "deductionDate": "2021-01-29T00:00:00Z" }', 'headers' => [ 'Authorization' => 'Bearer ', 'Content-Type' => 'application/json', ], ]); echo $response->getBody(); ``` **`CreateScheduledInvoice`** ```csharp CreateScheduledInvoice using RestSharp; var client = new RestClient("https://api.mercoa.com/invoice"); var request = new RestRequest(Method.POST); request.AddHeader("Authorization", "Bearer "); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "{\n \"status\": \"SCHEDULED\",\n \"payerId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\",\n \"creatorEntityId\": \"ent_8545a84e-a45f-41bf-bdf1-33b42a55812c\",\n \"vendorId\": \"ent_21661ac1-a2a8-4465-a6c0-64474ba8181d\",\n \"currency\": \"USD\",\n \"amount\": 100,\n \"invoiceDate\": \"2021-01-01T00:00:00Z\",\n \"dueDate\": \"2021-01-31T00:00:00Z\",\n \"paymentSourceId\": \"pm_4794d597-70dc-4fec-b6ec-c5988e759769\",\n \"paymentDestinationId\": \"pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18\",\n \"deductionDate\": \"2021-01-29T00:00:00Z\"\n}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` **`CreateScheduledInvoice`** ```swift CreateScheduledInvoice import Foundation let headers = [ "Authorization": "Bearer ", "Content-Type": "application/json" ] let parameters = [ "status": "SCHEDULED", "payerId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", "creatorEntityId": "ent_8545a84e-a45f-41bf-bdf1-33b42a55812c", "vendorId": "ent_21661ac1-a2a8-4465-a6c0-64474ba8181d", "currency": "USD", "amount": 100, "invoiceDate": "2021-01-01T00:00:00Z", "dueDate": "2021-01-31T00:00:00Z", "paymentSourceId": "pm_4794d597-70dc-4fec-b6ec-c5988e759769", "paymentDestinationId": "pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18", "deductionDate": "2021-01-29T00:00:00Z" ] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "https://api.mercoa.com/invoice")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "POST" request.allHTTPHeaderFields = headers request.httpBody = postData as Data let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error as Any) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume() ``` #### Update to New to Scheduled ### Request POST [https://api.mercoa.com/invoice/\{invoiceId}](https://api.mercoa.com/invoice/\{invoiceId}) **`NewToScheduled`** ```curl NewToScheduled curl -X POST https://api.mercoa.com/invoice/in_26e7b5d3-a739-4b23-9ad9-6aaa085f47a9 \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "deductionDate": "2021-01-29T00:00:00Z", "paymentDestinationId": "pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18", "status": "SCHEDULED" }' ``` **`NewToScheduled`** ```python NewToScheduled import requests url = "https://api.mercoa.com/invoice/in_26e7b5d3-a739-4b23-9ad9-6aaa085f47a9" payload = { "deductionDate": "2021-01-29T00:00:00Z", "paymentDestinationId": "pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18", "status": "SCHEDULED" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` **`NewToScheduled`** ```typescript NewToScheduled import { MercoaClient } from "@mercoa/javascript"; const client = new MercoaClient({ token: "YOUR_TOKEN" }); await client.invoice.update("in_26e7b5d3-a739-4b23-9ad9-6aaa085f47a9", { status: "SCHEDULED", paymentDestinationId: "pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18", deductionDate: new Date("2021-01-29T00:00:00.000Z") }); ``` **`NewToScheduled`** ```go NewToScheduled package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://api.mercoa.com/invoice/in_26e7b5d3-a739-4b23-9ad9-6aaa085f47a9" payload := strings.NewReader("{\n \"deductionDate\": \"2021-01-29T00:00:00Z\",\n \"paymentDestinationId\": \"pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18\",\n \"status\": \"SCHEDULED\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) } ``` **`NewToScheduled`** ```ruby NewToScheduled require 'uri' require 'net/http' url = URI("https://api.mercoa.com/invoice/in_26e7b5d3-a739-4b23-9ad9-6aaa085f47a9") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"deductionDate\": \"2021-01-29T00:00:00Z\",\n \"paymentDestinationId\": \"pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18\",\n \"status\": \"SCHEDULED\"\n}" response = http.request(request) puts response.read_body ``` **`NewToScheduled`** ```java NewToScheduled import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.post("https://api.mercoa.com/invoice/in_26e7b5d3-a739-4b23-9ad9-6aaa085f47a9") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"deductionDate\": \"2021-01-29T00:00:00Z\",\n \"paymentDestinationId\": \"pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18\",\n \"status\": \"SCHEDULED\"\n}") .asString(); ``` **`NewToScheduled`** ```php NewToScheduled request('POST', 'https://api.mercoa.com/invoice/in_26e7b5d3-a739-4b23-9ad9-6aaa085f47a9', [ 'body' => '{ "deductionDate": "2021-01-29T00:00:00Z", "paymentDestinationId": "pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18", "status": "SCHEDULED" }', 'headers' => [ 'Authorization' => 'Bearer ', 'Content-Type' => 'application/json', ], ]); echo $response->getBody(); ``` **`NewToScheduled`** ```csharp NewToScheduled using RestSharp; var client = new RestClient("https://api.mercoa.com/invoice/in_26e7b5d3-a739-4b23-9ad9-6aaa085f47a9"); var request = new RestRequest(Method.POST); request.AddHeader("Authorization", "Bearer "); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "{\n \"deductionDate\": \"2021-01-29T00:00:00Z\",\n \"paymentDestinationId\": \"pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18\",\n \"status\": \"SCHEDULED\"\n}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` **`NewToScheduled`** ```swift NewToScheduled import Foundation let headers = [ "Authorization": "Bearer ", "Content-Type": "application/json" ] let parameters = [ "deductionDate": "2021-01-29T00:00:00Z", "paymentDestinationId": "pm_5fde2f4a-facc-48ef-8f0d-6b7d087c7b18", "status": "SCHEDULED" ] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "https://api.mercoa.com/invoice/in_26e7b5d3-a739-4b23-9ad9-6aaa085f47a9")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "POST" request.allHTTPHeaderFields = headers request.httpBody = postData as Data let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error as Any) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume() ``` # 5. Pending On the `deductionDate`, at or before 1 PM Pacific Standard Time (PST) (4 PM Eastern Standard Time (EST)), the payment triggers, and the invoice is in the `PENDING` state. This means that the invoice amount and any applicable fees are deducted from the payer's account and sent to the vendor. No action is required, this is an automatic function. If the `deductionDate` is past 1 PM PST (4 PM EST) or if the date is a bank holiday or weekend, the payment triggers the next business day. If you are using your own payment rails, you are responsible for moving funds from the payer to the vendor when the invoice is set to the `PENDING` state. You can use [webhooks](/common-concepts/webhooks) to listen for this event. # 6. Paid When the invoice amount is received by the vendor, the invoice is set to the `PAID` state. If you are using custom payment rails, you are responsible for moving the invoice into this state once the funds have settled. # 7. Voiding Checks For invoices paid via mailed or printed checks, you have the ability to void the check if needed. This is useful in cases where: * A check was lost in the mail * A check was sent to the wrong address * A check needs to be stopped due to vendor issues * Any other scenario requiring check cancellation ## How to Void a Check ### Frontend (Mercoa UI) 1. Navigate to the invoice in the `PAID` status 2. Click the "Void Check" button next to the "View Check" button 3. Confirm the action in the popup dialog 4. The system will automatically: * Set the invoice status to `FAILED` * Update the associated transaction status to `FAILED` * Update all other invoices associated with the same transaction to `FAILED` ### Backend (API) To void a check programmatically, update the invoice status to `FAILED`. This will also update the transaction status to `FAILED` and all other invoices associated with the same transaction to `FAILED`. ## Important Notes * **Bank Contact Required**: After voiding in Mercoa, your customer must contact their bank directly to complete the void process * **Check Number**: Provide your bank with the check number from the voided check * **Timing**: The sooner you void a check, the higher the likelihood of successfully stopping payment * **Transaction Impact**: Voiding affects the entire transaction, not just the individual invoice * **Status Change**: Once voided, the invoice cannot be returned to `PAID` status without re-scheduling the payment ## Void Workflow 1. **Invoice Status**: Changes from `PAID` → `FAILED` 2. **Transaction Status**: Changes from `COMPLETED` → `FAILED` 3. **Associated Invoices**: All invoices in the same transaction are marked as `FAILED`