Edara API v3: Taxes
Read the guide first: authentication, paging, errors, rate limits and the shared PagedResult, BatchResult and *Reference shapes.
GET /v3/taxes: Lists taxes.GET /v3/taxes/{id}: Gets a tax by id.POST /v3/taxes: Creates a tax.PUT /v3/taxes/{id}: Updates a tax.DELETE /v3/taxes/{id}: Deletes a tax.GET /v3/taxes/einvoice-tax-types: Lists e-invoice tax types.
Endpoints
GET /v3/taxes: Lists taxes.
Operation GetTaxes · permission read:tax
Query string: GetTaxesQuery
| field | type | default | validation | description |
|---|---|---|---|---|
offset |
int? |
0 | >= 0 | Number of items to skip before returning results. Defaults to 0. |
limit |
int? |
100 | 1..1000 (out of range → 400) | Maximum number of items to return. Defaults to 100, maximum 1000. |
name |
string |
Must(name => !string.IsNullOrWhiteSpace(name)) .When(x => x.Name != null) | The tax name filter. | |
rate |
decimal? |
GreaterThanOrEqualTo(0m) .When(x => x.Rate.HasValue) | The tax rate filter. | |
scope |
TaxScope? |
Must(BeValidScope) .When(x => x.Scope.HasValue) | The scope filter. |
Responses: OK PagedResult<TaxResponse>: Paged list of taxes.
Notes
namematches any part of the tax name.ratemust match exactly, compared to four decimal places.scopeset toAnydoes not return every tax. It returns only taxes that have no scope. Omitscopeto get taxes of every scope.- Inactive taxes are included, so check
activeif you need only active ones. - Results are ordered by id. On an empty page, including when
offsetis past the end,totalCountis 0 instead of the real total. - An account reference that cannot be resolved is returned as null.
GET /v3/taxes/{id}: Gets a tax by id.
Operation GetTaxById · permission read:tax
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
id |
route | int |
The tax id. |
Responses: OK TaxResponse: The tax.
Notes
- Inactive taxes are returned. An unknown id returns
404. - A tax that has no scope is returned with
scopeset toAny.
POST /v3/taxes: Creates a tax.
Operation CreateTax · permission create:tax
Body: TaxUpsertRequest
| field | type | default | validation | description |
|---|---|---|---|---|
name |
string |
NotEmpty() | The tax name. | |
rate |
decimal |
InclusiveBetween(0m, 100m) | The tax rate percentage. | |
eInvoiceTaxTypeId |
int? |
GreaterThan(0) .When(x => x.EInvoiceTaxTypeId.HasValue) | The e-invoice tax type identifier. | |
scope |
TaxScope? |
Must(BeValidPersistedScope) .When(x => x.Scope.HasValue) | The tax scope. | |
salesAccountId |
int? |
GreaterThan(0) .When(x => x.SalesAccountId.HasValue) | The sales account identifier. | |
salesWithholdingAccountId |
int? |
GreaterThan(0) .When(x => x.SalesWithholdingAccountId.HasValue) | The sales withholding account identifier. | |
purchaseAccountId |
int? |
GreaterThan(0) .When(x => x.PurchaseAccountId.HasValue) | The purchase account identifier. | |
active |
bool |
Whether the tax is active. | ||
| (object rule) | RuleFor(x => x) .Must(HaveAtLeastOneAccount) .WithMessage("At least one tax account must be supplied.") |
Responses: Created TaxResponse: Tax created.
Business errors (HTTP 409, match on errorCode):
EInvoice_KSA_TaxRateCantBeGreaterThanZeroWithCategoryType: The KSA e-invoice category requires a zero tax rate.EInvoice_KSA_TaxRateCantBeZeroWithCategoryType: The KSA e-invoice category requires a non-zero tax rate.NameAlreadyExists: Another tax already uses the same name.NameContainsInvalidSpecialCharacters: The tax name contains unsupported special characters.TaxCannotSetBothTaxAndWithholdingTaxAccounts: The tax cannot use both tax and withholding accounts.TaxCannotUseDifferentPurchaseTaxAccount: PurchaseAccountId is already set for this tax setup. Repro: save the same tax with a different PurchaseAccountId.TaxCannotUseDifferentSalesTaxAccount: SalesAccountId is already set for this tax setup. Repro: save the same tax with a different SalesAccountId.TaxCannotUseDifferentSalesWithholdingAccount: SalesWithholdingAccountId is already set for this tax setup. Repro: save the same tax with a different SalesWithholdingAccountId.TaxInvalidEInvoiceType: The tax does not have an e-invoice tax type that matches the active country configuration.TaxPurchaseAndSalesAccountMustMatch: When both SalesAccountId and PurchaseAccountId are provided, they must point to the same account.
Notes
- All taxes in an organization must share one sales account, one sales withholding account, and one purchase account. Using a different account from the one already in use returns
409with anerrorCodethat starts withTaxCannotUseDifferent. - The sales account and the purchase account must be the same account. Otherwise the request returns
409TaxPurchaseAndSalesAccountMustMatch. - You cannot set a tax or purchase account together with a withholding account on the same tax. This returns
409TaxCannotSetBothTaxAndWithholdingTaxAccounts. - The tax name must be unique. A duplicate returns
409NameAlreadyExists. The name is also checked for special characters. - When the organization is connected to Egypt e-invoicing or e-receipts,
eInvoiceTaxTypeIdis required and must be an Egypt tax type. When the organization has connected to KSA e-invoicing before, it must be a KSA tax type. Otherwise the request returns409TaxInvalidEInvoiceType. This depends on the organization's setup, so handle the error in your code. - Omitting
scopeis the same as sendingAny. The tax is stored with no scope. - If you omit
active, the tax is created inactive. Sendactiveas true to create an active tax.
PUT /v3/taxes/{id}: Updates a tax.
Operation UpdateTax · permission update:tax
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
id |
route | int |
The tax id. |
Body: TaxUpsertRequest
| field | type | default | validation | description |
|---|---|---|---|---|
name |
string |
NotEmpty() | The tax name. | |
rate |
decimal |
InclusiveBetween(0m, 100m) | The tax rate percentage. | |
eInvoiceTaxTypeId |
int? |
GreaterThan(0) .When(x => x.EInvoiceTaxTypeId.HasValue) | The e-invoice tax type identifier. | |
scope |
TaxScope? |
Must(BeValidPersistedScope) .When(x => x.Scope.HasValue) | The tax scope. | |
salesAccountId |
int? |
GreaterThan(0) .When(x => x.SalesAccountId.HasValue) | The sales account identifier. | |
salesWithholdingAccountId |
int? |
GreaterThan(0) .When(x => x.SalesWithholdingAccountId.HasValue) | The sales withholding account identifier. | |
purchaseAccountId |
int? |
GreaterThan(0) .When(x => x.PurchaseAccountId.HasValue) | The purchase account identifier. | |
active |
bool |
Whether the tax is active. | ||
| (object rule) | RuleFor(x => x) .Must(HaveAtLeastOneAccount) .WithMessage("At least one tax account must be supplied.") |
Responses: OK TaxResponse: The updated tax.
Business errors (HTTP 409, match on errorCode):
EInvoice_KSA_TaxRateCantBeGreaterThanZeroWithCategoryType: The KSA e-invoice category requires a zero tax rate.EInvoice_KSA_TaxRateCantBeZeroWithCategoryType: The KSA e-invoice category requires a non-zero tax rate.NameAlreadyExists: Another tax already uses the same name.NameContainsInvalidSpecialCharacters: The tax name contains unsupported special characters.TaxCannotDeactivateRelatedToMasterData: The tax is attached to master data and cannot be deactivated.TaxCannotDeleteOrUpdateRelatedToTransactions: The tax is referenced by posted transactions or documents.TaxCannotSetBothTaxAndWithholdingTaxAccounts: The tax cannot use both tax and withholding accounts.TaxCannotUseDifferentPurchaseTaxAccount: PurchaseAccountId is already set for this tax setup. Repro: save the same tax with a different PurchaseAccountId.TaxCannotUseDifferentSalesTaxAccount: SalesAccountId is already set for this tax setup. Repro: save the same tax with a different SalesAccountId.TaxCannotUseDifferentSalesWithholdingAccount: SalesWithholdingAccountId is already set for this tax setup. Repro: save the same tax with a different SalesWithholdingAccountId.TaxInUseCannotDeactivateOrUpdate: The tax is already used and cannot be deactivated or changed.TaxInvalidEInvoiceType: The tax does not have an e-invoice tax type that matches the active country configuration.TaxPurchaseAndSalesAccountMustMatch: When both SalesAccountId and PurchaseAccountId are provided, they must point to the same account.
Notes
- An unknown id returns
404. - This is a full replace. Account ids you omit are cleared, and omitting
activedeactivates the tax. - If the tax is used in transactions, any change other than
activereturns409TaxCannotDeleteOrUpdateRelatedToTransactions. - If the tax is used in master data, a request that changes only
active, to deactivate or to reactivate, returns409TaxCannotDeactivateRelatedToMasterData. TaxInUseCannotDeactivateOrUpdateis listed but is not returned in practice.- The same rules as POST /v3/taxes apply: shared accounts across the organization, a unique name, and the e-invoice tax type.
DELETE /v3/taxes/{id}: Deletes a tax.
Operation DeleteTax · permission delete:tax
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
id |
route | int |
The tax id. |
Responses: NoContent: (not declared; read from the method body)
Business errors (HTTP 409, match on errorCode):
ItemCannotDeleteItInUse: The tax is referenced by other records.TaxCannotDeleteOrUpdateRelatedToTransactions: The tax is referenced by posted transactions or documents.
Notes
- An unknown id returns
404. - A tax used in transactions cannot be deleted. The request returns
409TaxCannotDeleteOrUpdateRelatedToTransactions. - The delete is permanent. If the tax is still referenced, for example by a stock item, the request returns
409ItemCannotDeleteItInUse.
GET /v3/taxes/einvoice-tax-types: Lists e-invoice tax types.
Operation GetEInvoiceTaxTypes · permission read:tax
Query string: GetEInvoiceTaxTypesQuery
| field | type | default | validation | description |
|---|---|---|---|---|
country |
string |
NotEmpty() | The country filter. |
Responses: OK IReadOnlyCollection<EInvoiceTaxTypeResponse>: List of e-invoice tax types.
Notes
countrymust match a country name exactly, for exampleEgyptorKSA. Partial names do not match.- An unknown
countryreturns200with an empty list, not404. The list is not paged.
Types
AccountReference
Lightweight account reference (id + code + name).
| field | type | description |
|---|---|---|
id |
int |
The account id. |
code |
string |
The account code. |
name |
string |
The account name. |
EInvoiceTaxTypeResponse
Response describing an e-invoice tax type.
| field | type | description |
|---|---|---|
id |
int |
The tax type identifier. |
description |
string |
The tax type description. |
type |
string |
The tax type. |
code |
string |
The external-system code. |
country |
string |
The country the tax type applies to. |
TaxResponse
Response describing a tax.
| field | type | description |
|---|---|---|
id |
int |
The tax identifier. |
name |
string |
The tax name. |
rate |
decimal |
The tax rate percentage. |
eInvoiceTaxTypeId |
int? |
The e-invoice tax type identifier. |
scope |
TaxScope |
The tax scope. |
salesAccount |
AccountReference |
The sales account reference. |
salesWithholdingAccount |
AccountReference |
The sales withholding account reference. |
purchaseAccount |
AccountReference |
The purchase account reference. |
active |
bool |
Whether the tax is active. |
TaxScope
Tax scopes exposed by the v3 API.
Values (sent/returned as the name): Any=0 (Any scope.), StockItem=1 (Stock items.), ServiceItem=2 (Service items.)