curl --request POST \
--url https://api.arcuserp.com/v1/ar/assess-late-fees \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"account_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"dry_run": false
}
'import requests
url = "https://api.arcuserp.com/v1/ar/assess-late-fees"
payload = {
"account_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"dry_run": False
}
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({account_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a', dry_run: false})
};
fetch('https://api.arcuserp.com/v1/ar/assess-late-fees', 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/ar/assess-late-fees",
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([
'account_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'dry_run' => false
]),
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/ar/assess-late-fees"
payload := strings.NewReader("{\n \"account_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"dry_run\": false\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/ar/assess-late-fees")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"account_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"dry_run\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.arcuserp.com/v1/ar/assess-late-fees")
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 \"account_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"dry_run\": false\n}"
response = http.request(request)
puts response.read_body{
"assessed": [
{
"source_order_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"late_fee_order_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"account_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"customer_name": "<string>",
"invoice_number": "<string>",
"balance_due": 123,
"fee_amount": 123,
"days_overdue": 123,
"compounding": "monthly"
}
],
"skipped": [
{
"source_order_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"account_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"reason": "<string>"
}
],
"total_fee_amount": 123,
"dry_run": true
}{
"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"
}Assess late fees (finance charges)
accounting:writeTriggers finance charge assessment for the entity. By default assesses all overdue
invoices for all active customer accounts. Pass account_id to scope to a single
customer. Pass dry_run: true to preview which invoices would receive a charge and
the calculated amounts without persisting any records.
Assessment logic: For each overdue invoice the handler checks eligibility
(account not late-fee-exempt, invoice status open/partially_paid, balance_due
meets the entity minimum, grace period elapsed, no same-day duplicate). The fee
is calculated per the entity compounding mode (monthly, daily, or none).
A new late_fee_invoice document is created and a GL journal entry is posted
(DR accounts_receivable 1300 / CR finance_charge_income 4220) per ASC 310-10-35.
Entity settings required: late_fee_enabled must be true and
late_fee_rate_percent must be a non-null positive number in the entity settings
before any charges are assessed.
Idempotency: At most one late-fee invoice is issued per source invoice per day.
Repeated calls on the same day return skipped results for already-charged invoices.
curl --request POST \
--url https://api.arcuserp.com/v1/ar/assess-late-fees \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"account_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"dry_run": false
}
'import requests
url = "https://api.arcuserp.com/v1/ar/assess-late-fees"
payload = {
"account_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"dry_run": False
}
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({account_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a', dry_run: false})
};
fetch('https://api.arcuserp.com/v1/ar/assess-late-fees', 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/ar/assess-late-fees",
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([
'account_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'dry_run' => false
]),
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/ar/assess-late-fees"
payload := strings.NewReader("{\n \"account_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"dry_run\": false\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/ar/assess-late-fees")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"account_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"dry_run\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.arcuserp.com/v1/ar/assess-late-fees")
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 \"account_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"dry_run\": false\n}"
response = http.request(request)
puts response.read_body{
"assessed": [
{
"source_order_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"late_fee_order_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"account_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"customer_name": "<string>",
"invoice_number": "<string>",
"balance_due": 123,
"fee_amount": 123,
"days_overdue": 123,
"compounding": "monthly"
}
],
"skipped": [
{
"source_order_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"account_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"reason": "<string>"
}
],
"total_fee_amount": 123,
"dry_run": true
}{
"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.
Body
Response
Late fee assessment results
Invoices that received a finance charge
Show child attributes
Show child attributes
Invoices that were evaluated but skipped (exempt, already charged today, min not met, etc.)
Show child attributes
Show child attributes
Sum of all fee_amount values in the assessed array
Reflects the dry_run parameter; true means no records were persisted
Was this page helpful?

