curl --request POST \
--url https://api.arcuserp.com/v1/entities/{entity_id}/reconciliation/match-journal-entry \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"bank_transaction_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"journal_entry_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"reconciliation_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"difference_reason": "<string>",
"difference_gl_account_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
'import requests
url = "https://api.arcuserp.com/v1/entities/{entity_id}/reconciliation/match-journal-entry"
payload = {
"bank_transaction_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"journal_entry_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"reconciliation_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"difference_reason": "<string>",
"difference_gl_account_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
bank_transaction_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
journal_entry_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
reconciliation_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
difference_reason: '<string>',
difference_gl_account_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a'
})
};
fetch('https://api.arcuserp.com/v1/entities/{entity_id}/reconciliation/match-journal-entry', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.arcuserp.com/v1/entities/{entity_id}/reconciliation/match-journal-entry",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'bank_transaction_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'journal_entry_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'reconciliation_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'difference_reason' => '<string>',
'difference_gl_account_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.arcuserp.com/v1/entities/{entity_id}/reconciliation/match-journal-entry"
payload := strings.NewReader("{\n \"bank_transaction_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"journal_entry_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"reconciliation_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"difference_reason\": \"<string>\",\n \"difference_gl_account_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.arcuserp.com/v1/entities/{entity_id}/reconciliation/match-journal-entry")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"bank_transaction_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"journal_entry_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"reconciliation_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"difference_reason\": \"<string>\",\n \"difference_gl_account_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.arcuserp.com/v1/entities/{entity_id}/reconciliation/match-journal-entry")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"bank_transaction_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"journal_entry_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"reconciliation_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"difference_reason\": \"<string>\",\n \"difference_gl_account_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}"
response = http.request(request)
puts response.read_body{
"bank_transaction_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"journal_entry_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"entry_number": "<string>",
"matched": true,
"entry_bank_net": 123,
"entry_net_all_bank_gls": 123,
"entry_bank_gl_count": 123,
"transfer_counterparty": {
"bank_account_name": "<string>",
"gl_account_number": "<string>"
},
"amount_warning": "<string>",
"posted_journal_entry": true,
"book_side": {
"stamped": 123,
"line_ids": [
"3c90c3cc-0d44-4b50-8888-8dd25736052a"
],
"reason": "no_leg_on_bank_gl",
"historical_import": true,
"correction_legs": [
{
"journal_entry_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"entry_number": "<string>",
"entry_date": "2023-12-25",
"stamped": 123
}
]
}
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}Match a bank line to a journal entry
Links a bank feed line to cash the books already record as a posted journal entry, such as a bank-initiated fee or a manual correction. Posts no new journal entry; it only closes out the bank-feed side of an amount that was already booked.
curl --request POST \
--url https://api.arcuserp.com/v1/entities/{entity_id}/reconciliation/match-journal-entry \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"bank_transaction_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"journal_entry_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"reconciliation_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"difference_reason": "<string>",
"difference_gl_account_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
'import requests
url = "https://api.arcuserp.com/v1/entities/{entity_id}/reconciliation/match-journal-entry"
payload = {
"bank_transaction_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"journal_entry_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"reconciliation_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"difference_reason": "<string>",
"difference_gl_account_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
bank_transaction_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
journal_entry_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
reconciliation_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
difference_reason: '<string>',
difference_gl_account_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a'
})
};
fetch('https://api.arcuserp.com/v1/entities/{entity_id}/reconciliation/match-journal-entry', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.arcuserp.com/v1/entities/{entity_id}/reconciliation/match-journal-entry",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'bank_transaction_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'journal_entry_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'reconciliation_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'difference_reason' => '<string>',
'difference_gl_account_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.arcuserp.com/v1/entities/{entity_id}/reconciliation/match-journal-entry"
payload := strings.NewReader("{\n \"bank_transaction_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"journal_entry_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"reconciliation_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"difference_reason\": \"<string>\",\n \"difference_gl_account_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.arcuserp.com/v1/entities/{entity_id}/reconciliation/match-journal-entry")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"bank_transaction_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"journal_entry_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"reconciliation_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"difference_reason\": \"<string>\",\n \"difference_gl_account_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.arcuserp.com/v1/entities/{entity_id}/reconciliation/match-journal-entry")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"bank_transaction_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"journal_entry_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"reconciliation_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"difference_reason\": \"<string>\",\n \"difference_gl_account_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}"
response = http.request(request)
puts response.read_body{
"bank_transaction_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"journal_entry_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"entry_number": "<string>",
"matched": true,
"entry_bank_net": 123,
"entry_net_all_bank_gls": 123,
"entry_bank_gl_count": 123,
"transfer_counterparty": {
"bank_account_name": "<string>",
"gl_account_number": "<string>"
},
"amount_warning": "<string>",
"posted_journal_entry": true,
"book_side": {
"stamped": 123,
"line_ids": [
"3c90c3cc-0d44-4b50-8888-8dd25736052a"
],
"reason": "no_leg_on_bank_gl",
"historical_import": true,
"correction_legs": [
{
"journal_entry_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"entry_number": "<string>",
"entry_date": "2023-12-25",
"stamped": 123
}
]
}
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}Authorizations
API key issued per entity via Settings > Developers > API Keys.
Each key carries scopes (e.g. orders:read, products:write).
Bearer token format: Authorization: Bearer ark_live_ent_Test keys use ark_test_ent_. Both are issued per entity
via Settings > Developers > API Keys.
Headers
Deduplicates retried match submissions for 24 hours.
255Path Parameters
Body
The bank transaction to match. Must be unreconciled, not excluded and not pending.
The posted journal entry that already carries this cash. Must not be voided, must not be claimed by another bank transaction, and its reversal chain must net to LIVE (even depth). A restored entry, one whose reversal was itself reversed, is live and is accepted.
Optional open bank-reconciliation to attach the match to.
REQUIRED, with difference_gl_account_id, when the entry is a bank deposit ticket whose total differs from this bank line (lane R6-AF). What the difference actually was, in the operator's own words: a check that was deposited but never recorded, a bank correction, a fee. It becomes the adjustment entry's description and its offsetting line's memo. Ignored for every other kind of entry.
500REQUIRED, with difference_reason, when the entry is a bank deposit ticket whose total differs from this bank line. The postable leaf account the difference belongs to. Must satisfy the usual postability rules and lie in an open period, or the adjustment refuses. Ignored for every other kind of entry.
Response
Match recorded. No journal entry was posted, UNLESS this was a bank deposit ticket whose named difference was posted as its own dated adjustment, which posted_journal_entry: true and the deposit_difference object report.
The entry's signed bank-side net, read from the ledger and comparable to the bank line's signed amount. For an entry that touches ONE bank GL this is the net across that GL, which is what it has always been. For a TRANSFER (an entry touching two or more of this entity's bank GLs and carrying a leg on THIS line's own GL) it is the net on THIS line's GL alone, because the entry-wide net of a transfer is 0.00 by construction. Read entry_bank_gl_count to tell which basis was used, and entry_net_all_bank_gls for the entry-wide figure.
The entry's net across ALL of this entity's bank GL accounts, always, whatever basis entry_bank_net used. Equal to entry_bank_net for a single-bank-GL entry and 0.00 for a transfer. Published so that no integrator that read entry_bank_net before 2026-09-21 loses a number.
How many DISTINCT bank GL accounts of this entity the entry touches. 1 for an ordinary entry; 2 for a transfer between your own accounts.
Present (non-null) only when the entry is a transfer and carries a leg on this line's own bank GL. Names the account holding the far leg, so a confirmation screen can say so without a second call. Null otherwise.
Show child attributes
Show child attributes
Set when the bank amount and entry_bank_net differ by more than half a cent, on whichever basis that field used. Advisory, never a refusal.
Always false. This verb records a link and posts no GL.
What the GENERAL LEDGER now says about the money this bank line explains. Added 2026-09-19 by BANKFEED wave 4 lane W4-G, and it is purely additive: no request field changed and no existing response field changed meaning.
A bank reconciliation has two sides. The bank side is
reconciliation_status on the bank transaction. The BOOK side is
reconciled_at on the journal entry's line on that bank account's GL
account, and until this lane no verb outside a statement session ever
wrote it, so matched money could read UNCLEARED in the ledger forever.
STILL NO GL IS POSTED. The stamp writes no debit and no credit; the trial balance is identical before and after, and a closed period cannot be moved by it. What it changes is which lines the reconciliation workbench and the bank register's open-items tile still treat as outstanding.
stamped: 0 with a reason is an honest answer, not an error:
no_leg_on_bank_gl means the entry carries no line on THIS account's GL
(a payout settled to a different account, for example);
already_reconciled means a session or a baseline had already cleared
it; missing_argument means the record carries no journal entry to
stamp.
Show child attributes
Show child attributes
Was this page helpful?

