> 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/gl-accounts/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.mercoa.com/_mcp/server. GL (General Ledger) accounts can be used to categorize line items on invoices for accounting purposes. Mercoa provides functionality to manage GL accounts and optionally use AI to predict appropriate GL accounts for invoice line items. ## Setting Up GL Accounts GL accounts are stored in entity metadata. To add or update GL accounts for an entity, update the entity's `glAccountId` metadata key with an array of GL account objects: Plain string values: ### Request POST [https://api.mercoa.com/entity/\{entityId}/metadata/\{key}](https://api.mercoa.com/entity/\{entityId}/metadata/\{key}) **`GLAccounts`** ```curl GLAccounts curl -X POST https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/metadata/glAccountId \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '[ "{key: '\''60205'\'', value: '\''60205 Marketing Expense'\''}", "{key: '\''60215'\'', value: '\''60215 Office Expense'\''}", "{key: '\''60225'\'', value: '\''60225 Payroll Expense'\''}", "{key: '\''60550'\'', value: '\''60550 Rent Expense'\''}" ]' ``` **`GLAccounts`** ```python GLAccounts import requests url = "https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/metadata/glAccountId" payload = ["{key: '60205', value: '60205 Marketing Expense'}", "{key: '60215', value: '60215 Office Expense'}", "{key: '60225', value: '60225 Payroll Expense'}", "{key: '60550', value: '60550 Rent Expense'}"] headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` **`GLAccounts`** ```typescript GLAccounts import { MercoaClient } from "@mercoa/javascript"; const client = new MercoaClient({ token: "YOUR_TOKEN" }); await client.entity.metadata.update("ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced", "glAccountId", ["{key: '60205', value: '60205 Marketing Expense'}", "{key: '60215', value: '60215 Office Expense'}", "{key: '60225', value: '60225 Payroll Expense'}", "{key: '60550', value: '60550 Rent Expense'}"]); ``` **`GLAccounts`** ```go GLAccounts package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/metadata/glAccountId" payload := strings.NewReader("[\n \"{key: '60205', value: '60205 Marketing Expense'}\",\n \"{key: '60215', value: '60215 Office Expense'}\",\n \"{key: '60225', value: '60225 Payroll Expense'}\",\n \"{key: '60550', value: '60550 Rent Expense'}\"\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)) } ``` **`GLAccounts`** ```ruby GLAccounts require 'uri' require 'net/http' url = URI("https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/metadata/glAccountId") 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 \"{key: '60205', value: '60205 Marketing Expense'}\",\n \"{key: '60215', value: '60215 Office Expense'}\",\n \"{key: '60225', value: '60225 Payroll Expense'}\",\n \"{key: '60550', value: '60550 Rent Expense'}\"\n]" response = http.request(request) puts response.read_body ``` **`GLAccounts`** ```java GLAccounts import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.post("https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/metadata/glAccountId") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("[\n \"{key: '60205', value: '60205 Marketing Expense'}\",\n \"{key: '60215', value: '60215 Office Expense'}\",\n \"{key: '60225', value: '60225 Payroll Expense'}\",\n \"{key: '60550', value: '60550 Rent Expense'}\"\n]") .asString(); ``` **`GLAccounts`** ```php GLAccounts request('POST', 'https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/metadata/glAccountId', [ 'body' => '[ "{key: \'60205\', value: \'60205 Marketing Expense\'}", "{key: \'60215\', value: \'60215 Office Expense\'}", "{key: \'60225\', value: \'60225 Payroll Expense\'}", "{key: \'60550\', value: \'60550 Rent Expense\'}" ]', 'headers' => [ 'Authorization' => 'Bearer ', 'Content-Type' => 'application/json', ], ]); echo $response->getBody(); ``` **`GLAccounts`** ```csharp GLAccounts using RestSharp; var client = new RestClient("https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/metadata/glAccountId"); var request = new RestRequest(Method.POST); request.AddHeader("Authorization", "Bearer "); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "[\n \"{key: '60205', value: '60205 Marketing Expense'}\",\n \"{key: '60215', value: '60215 Office Expense'}\",\n \"{key: '60225', value: '60225 Payroll Expense'}\",\n \"{key: '60550', value: '60550 Rent Expense'}\"\n]", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` **`GLAccounts`** ```swift GLAccounts import Foundation let headers = [ "Authorization": "Bearer ", "Content-Type": "application/json" ] let parameters = ["{key: '60205', value: '60205 Marketing Expense'}", "{key: '60215', value: '60215 Office Expense'}", "{key: '60225', value: '60225 Payroll Expense'}", "{key: '60550', value: '60550 Rent Expense'}"] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/metadata/glAccountId")! 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() ``` JSON values with subtitles: ### Request POST [https://api.mercoa.com/entity/\{entityId}/metadata/\{key}](https://api.mercoa.com/entity/\{entityId}/metadata/\{key}) **`GLAccountsWithSubtitles`** ```curl GLAccountsWithSubtitles curl -X POST https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/metadata/glAccountId \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '[ "{key: '\''60205'\'', value: {value: '\''60205 Marketing Expense'\'', subtitle: '\''Expense'\''}}", "{key: '\''60215'\'', value: {value: '\''60215 Office Expense'\'', subtitle: '\''Expense'\''}}", "{key: '\''60225'\'', value: {value: '\''60225 Payroll Expense'\'', subtitle: '\''Expense'\''}}", "{key: '\''60550'\'', value: {value: '\''60550 Rent Expense'\'', subtitle: '\''Expense'\''}}" ]' ``` **`GLAccountsWithSubtitles`** ```python GLAccountsWithSubtitles import requests url = "https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/metadata/glAccountId" payload = ["{key: '60205', value: {value: '60205 Marketing Expense', subtitle: 'Expense'}}", "{key: '60215', value: {value: '60215 Office Expense', subtitle: 'Expense'}}", "{key: '60225', value: {value: '60225 Payroll Expense', subtitle: 'Expense'}}", "{key: '60550', value: {value: '60550 Rent Expense', subtitle: 'Expense'}}"] headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` **`GLAccountsWithSubtitles`** ```typescript GLAccountsWithSubtitles import { MercoaClient } from "@mercoa/javascript"; const client = new MercoaClient({ token: "YOUR_TOKEN" }); await client.entity.metadata.update("ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced", "glAccountId", ["{key: '60205', value: {value: '60205 Marketing Expense', subtitle: 'Expense'}}", "{key: '60215', value: {value: '60215 Office Expense', subtitle: 'Expense'}}", "{key: '60225', value: {value: '60225 Payroll Expense', subtitle: 'Expense'}}", "{key: '60550', value: {value: '60550 Rent Expense', subtitle: 'Expense'}}"]); ``` **`GLAccountsWithSubtitles`** ```go GLAccountsWithSubtitles package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/metadata/glAccountId" payload := strings.NewReader("[\n \"{key: '60205', value: {value: '60205 Marketing Expense', subtitle: 'Expense'}}\",\n \"{key: '60215', value: {value: '60215 Office Expense', subtitle: 'Expense'}}\",\n \"{key: '60225', value: {value: '60225 Payroll Expense', subtitle: 'Expense'}}\",\n \"{key: '60550', value: {value: '60550 Rent Expense', subtitle: 'Expense'}}\"\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)) } ``` **`GLAccountsWithSubtitles`** ```ruby GLAccountsWithSubtitles require 'uri' require 'net/http' url = URI("https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/metadata/glAccountId") 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 \"{key: '60205', value: {value: '60205 Marketing Expense', subtitle: 'Expense'}}\",\n \"{key: '60215', value: {value: '60215 Office Expense', subtitle: 'Expense'}}\",\n \"{key: '60225', value: {value: '60225 Payroll Expense', subtitle: 'Expense'}}\",\n \"{key: '60550', value: {value: '60550 Rent Expense', subtitle: 'Expense'}}\"\n]" response = http.request(request) puts response.read_body ``` **`GLAccountsWithSubtitles`** ```java GLAccountsWithSubtitles import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.post("https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/metadata/glAccountId") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("[\n \"{key: '60205', value: {value: '60205 Marketing Expense', subtitle: 'Expense'}}\",\n \"{key: '60215', value: {value: '60215 Office Expense', subtitle: 'Expense'}}\",\n \"{key: '60225', value: {value: '60225 Payroll Expense', subtitle: 'Expense'}}\",\n \"{key: '60550', value: {value: '60550 Rent Expense', subtitle: 'Expense'}}\"\n]") .asString(); ``` **`GLAccountsWithSubtitles`** ```php GLAccountsWithSubtitles request('POST', 'https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/metadata/glAccountId', [ 'body' => '[ "{key: \'60205\', value: {value: \'60205 Marketing Expense\', subtitle: \'Expense\'}}", "{key: \'60215\', value: {value: \'60215 Office Expense\', subtitle: \'Expense\'}}", "{key: \'60225\', value: {value: \'60225 Payroll Expense\', subtitle: \'Expense\'}}", "{key: \'60550\', value: {value: \'60550 Rent Expense\', subtitle: \'Expense\'}}" ]', 'headers' => [ 'Authorization' => 'Bearer ', 'Content-Type' => 'application/json', ], ]); echo $response->getBody(); ``` **`GLAccountsWithSubtitles`** ```csharp GLAccountsWithSubtitles using RestSharp; var client = new RestClient("https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/metadata/glAccountId"); var request = new RestRequest(Method.POST); request.AddHeader("Authorization", "Bearer "); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "[\n \"{key: '60205', value: {value: '60205 Marketing Expense', subtitle: 'Expense'}}\",\n \"{key: '60215', value: {value: '60215 Office Expense', subtitle: 'Expense'}}\",\n \"{key: '60225', value: {value: '60225 Payroll Expense', subtitle: 'Expense'}}\",\n \"{key: '60550', value: {value: '60550 Rent Expense', subtitle: 'Expense'}}\"\n]", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` **`GLAccountsWithSubtitles`** ```swift GLAccountsWithSubtitles import Foundation let headers = [ "Authorization": "Bearer ", "Content-Type": "application/json" ] let parameters = ["{key: '60205', value: {value: '60205 Marketing Expense', subtitle: 'Expense'}}", "{key: '60215', value: {value: '60215 Office Expense', subtitle: 'Expense'}}", "{key: '60225', value: {value: '60225 Payroll Expense', subtitle: 'Expense'}}", "{key: '60550', value: {value: '60550 Rent Expense', subtitle: 'Expense'}}"] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "https://api.mercoa.com/entity/ent_a0f6ea94-0761-4a5e-a416-3c453cb7eced/metadata/glAccountId")! 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() ``` GL Accounts can also be automatically synced using [Accounting Sync](/accounts-payable/accounting-sync). ## Using GL Accounts If you use Mercoa's React Component Library, line items show a dropdown of GL accounts for the entity. When selected, the `glAccountId` is added to the line item as a special `glAccountId` field in the `lineItem` object. It's not added to the `lineItem.metadata` object. This `glAccountId` field can be used to [filter invoices](/api-reference/entity/invoice/find#request.query.lineItemGlAccountId) by GL account. ## Using AI to Predict GL Accounts Mercoa can use AI to predict GL accounts for line items. To enable this: 1. Make sure the entity has a `glAccountId` metadata key set with the list of GL accounts provided in the previous section. 2. Make sure the [predictMetadata](/api-reference/entity/customization/update#request.body.ocr.predictMetadata) is set to true for the entity (defaults to true). 3. Make sure all [lineItem ocr fields](/api-reference/entity/customization/update#request.body.ocr) are set to true (defaults to true). Mercoa needs the user to manually tag the GL accounts for the first invoice. Once the initial invoice is created and manually tagged with GL accounts, the AI can predict line item GL accounts for new invoices from the same vendor.