Prerequisites
Before you apply withholding tax through the API, confirm the following:- API key: Your requests send your organization’s API key in the
X-API-KEYheader. See authenticating your requests. - Withholding tax rates: The rates are set up in the app under Configuration → Tax Setup → Withholding Rates. The API reads rates but can’t create them. See How to Set Up Withholding Tax.
- Company address: The company has an address with a country. A rate applies only to records of a company in the rate’s country.
- Accounts and vendors: You have a liability account (type
other_current_liabilityorlong_term_liability) for withheld tax, and a vendor withvendor_typetax_agencyfor the tax authority.
Look up withholding tax rates
Withholding tax rates are read-only in the API. List them to find theid to send as withholding_tax_rate_id on a line. The active_on filter returns only the rates that are valid on a date, which is the record date you plan to use.
rate is a fraction, so 0.100000 is 10%.
Set a vendor’s withholding tax defaults
A vendor’s withholding fields are writable on create,PUT, and PATCH. On PUT and PATCH, an omitted field keeps its stored value, and null clears an ID field. The following request turns on withholding tax for a vendor and sets its defaults:
withholding_tax_rate_id on each line. The default payable account is used when a bill or direct expense with withholding tax has no withholding_tax_payable_account_id.
The vendor withholding tax fields are listed below.
Create a bill with withholding tax
To withhold tax on a bill or direct expense line, sendwithholding_tax_rate_id on the line. DualEntry calculates the withheld amount as the line’s net amount (before VAT, GST, or sales tax) multiplied by the rate, rounded to two decimal places. The following request creates a posted bill with one 1,000.00 line at 10%:
withholding_tax_payable_account_id, or send null, DualEntry uses the vendor’s default_withholding_tax_payable_account_id. A record with withholding tax needs one of the two. Direct expenses take the same fields on their items lines. Recurring bill templates accept them in record_payload, and each bill the template creates gets the withholding tax.
Update withholding tax on a record
On an update, a line keeps its withholding tax unless you sendwithholding_tax_rate_id for it. DualEntry matches each line you send to its stored line by the line id, then reads withholding_tax_rate_id as follows:
- Field omitted: The line keeps its stored rate. This stops clients that don’t know about withholding tax from removing it.
null: The line’s withholding tax is removed.- A rate ID: The line uses the new rate.
- New line: A line sent with no
idis a new line, with only the withholding tax you send.
withholding_tax_payable_account_id works the same way: omit it to keep the stored account. Bills support this on PUT and PATCH, and direct expenses on PUT. Vendor credits have no header payable account.
A bill PATCH that sends expenses or items replaces that whole list, so include every line you want to keep. The following request removes the withholding tax from line 555:
Reverse withholding tax with a vendor credit
A vendor credit line reverses withholding tax by linking to a bill line withcredited_bill_line_id. The line takes the bill line’s rate and payable account, so vendor credits have no withholding_tax_rate_id or header payable account. The reversed amount is the bill line’s rate multiplied by the credit line’s net amount, up to the bill line’s withholding tax that isn’t already reversed.
For example, a vendor credit line of 300.00 with "credited_bill_line_id": 555 reverses 30.00 of a 10% bill line. The vendor credit returns amount "270.00", withholding_tax_total "30.00", and a credited_bill_line object with the bill line’s id, bill_id, bill_number, and position.
The bill line must be on a posted bill with the same vendor, company, and currency. On a PUT, a line that omits credited_bill_line_id keeps its link, and null removes the link and the withholding tax.
Remit withheld tax to a tax agency
A withholding remittance records a payment to a tax agency for open withheld amounts. A withheld amount is open when its record is posted and it isn’t on a draft or posted remittance. Remit in two steps. First, list the open withheld amounts for a company. Amounts are in the company’s base currency, and vendor credit amounts are negative.withheld_entry_id values you’re paying. Each amount is remitted in full.
total, and locks the source lines. The request body fields are listed below.
The withholding tax endpoints are listed below. The remittances resource has no update or archive endpoint: archive a remittance in the app.
The same endpoints are available under
/public/v3-alpha/.
Permissions
Each endpoint needs a permission on the API key’s role. The open items list and remittance create need permission to create vendor payments, the same as remittances in the app.
A key without the permission gets
403. Withholding tax fields on bills, direct expenses, vendor credits, and vendors use those resources’ existing permissions. For an open-items request with a company_id outside the key’s access, the API returns 200 with an empty items list.
An API key carries the permissions of the roles you choose when you create it. An integration that only reads withholding tax, such as one that exports remittances, needs the view permissions. An integration that also remits needs vendor payment create. If a call returns 403, add a role with the missing permission to the key, or create a new key with the right roles. The API can’t archive a remittance, so a user with permission to archive vendor payments must do it in the app. See How to Give an Integration Access to DualEntry.
Errors
Withholding tax validation errors return422. The most common messages are listed below.
For the error response format, see Errors.
Related pages
- Withholding Tax: how withholding tax works in the app
- How to Calculate Tax Before Creating an Invoice or Bill: VAT, GST, and sales tax on write
- Pagination:
limitandoffseton list endpoints