DonutworkHelp Center
Api ReferenceOrganizzazione
Documentazione Donutwork

Taxes

Manage regional tax profiles, automate VAT calculations, and ensure billing compliance across global markets.

Taxes API

The Taxes API provides a centralized layer for managing tax profiles and regional tax logic. By defining tax profiles (such as VAT, GST, or Sales Tax), organizations can automate tax calculation during invoicing and subscription renewals, ensuring consistent compliance with local regulations.


Tax Profiles

List Tax Profiles

Retrieve a comprehensive directory of all tax profiles configured for your organization. These profiles act as the authoritative source for tax percentage calculations and must be referenced when provisiong new customers or products.

GET
/2026-02-01/taxes.json
Required permissiontaxes:read

Path, query, and header parameters

sizeinteger· query
Maximum records per page (max 100).
pageinteger· query
Target page index for results.

Responses

Tax profile directory successfully retrieved.

{
  "entities": "Taxes",
  "count": 5,
  "per_page": 100,
  "pages": {
    "current": 1,
    "max": 1
  },
  "elements": [
    {
      "id": "66a151b7...",
      "name": "Standard EU VAT (22%)",
      "percentage": 22,
      "description": "Standard Value Added Tax for European Union member states."
    }
  ]
}

Request examples

curl --request GET 'https://api.hub.donutwork.com/2026-02-01/taxes.json' \
  --header 'Authorization: Bearer YOUR_API_KEY'
const response = await fetch('https://api.hub.donutwork.com/2026-02-01/taxes.json', {
  method: 'GET',
  headers: {
    Authorization: 'Bearer ' + process.env.DONUTWORK_API_KEY,
  },
});
const requestId = response.headers.get('x-request-id');
if (!response.ok) {
  const error = await response.text();
  throw new Error(`${response.status} ${error} [${requestId}]`);
}
const contentType = response.headers.get('content-type') ?? '';
const data = response.status === 204 ? null
  : contentType.includes('application/json') ? await response.json()
  : await response.text();
$request = curl_init('https://api.hub.donutwork.com/2026-02-01/taxes.json');
curl_setopt_array($request, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('DONUTWORK_API_KEY'),
    ],
]);
$response = curl_exec($request);
if ($response === false) {
    $error = curl_error($request);
    curl_close($request);
    throw new RuntimeException($error);
}
$status = curl_getinfo($request, CURLINFO_RESPONSE_CODE);
$contentType = (string) curl_getinfo($request, CURLINFO_CONTENT_TYPE);
curl_close($request);
if ($status >= 400) { throw new RuntimeException($response); }
$data = $status === 204 ? null
    : (str_contains($contentType, 'application/json')
        ? json_decode($response, true, flags: JSON_THROW_ON_ERROR) : $response);

Replace uppercase placeholders and sample values with your own data and company resource IDs. Keep the API key on a trusted server. Reuse an idempotency key only for the same logical request and payload.

Technical Implementation

Integration Note: When orchestrating customer provisioning (via the CRM/Customer API), ensure the tax_id from these profiles is correctly mapped. This association is critical for accurate automated invoicing and financial reporting.


Tax Profile Lifecycle

Create Tax Profile

POST
/2026-02-01/taxes.json
Required permissiontaxes:write

Path, query, and header parameters

No path, query, or additional header parameters.

Request Body

JSON
{
  "tax": {
    "name": "Standard EU VAT (22%)",
    "description": "EU default VAT profile",
    "percentage": 22,
    "default": false
  }
}
tax.namestringRequired
Unique tax profile label.
tax.percentagenumberRequired
Tax percentage value. Must be >= 0.
tax.descriptionstring
Optional internal description.
tax.defaultboolean
Marks the profile as default when true.

Responses

Tax profile created.

{
  "status": "success",
  "tax": {
    "id": "tax_001",
    "name": "Standard EU VAT (22%)",
    "percentage": 22
  }
}

Request examples

curl --request POST 'https://api.hub.donutwork.com/2026-02-01/taxes.json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
  "tax": {
    "name": "Standard EU VAT (22%)",
    "description": "EU default VAT profile",
    "percentage": 22,
    "default": false
  }
}'
const response = await fetch('https://api.hub.donutwork.com/2026-02-01/taxes.json', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer ' + process.env.DONUTWORK_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "tax": {
      "name": "Standard EU VAT (22%)",
      "description": "EU default VAT profile",
      "percentage": 22,
      "default": false
    }
  }),
});
const requestId = response.headers.get('x-request-id');
if (!response.ok) {
  const error = await response.text();
  throw new Error(`${response.status} ${error} [${requestId}]`);
}
const contentType = response.headers.get('content-type') ?? '';
const data = response.status === 204 ? null
  : contentType.includes('application/json') ? await response.json()
  : await response.text();
$request = curl_init('https://api.hub.donutwork.com/2026-02-01/taxes.json');
curl_setopt_array($request, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('DONUTWORK_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => '{
  "tax": {
    "name": "Standard EU VAT (22%)",
    "description": "EU default VAT profile",
    "percentage": 22,
    "default": false
  }
}',
]);
$response = curl_exec($request);
if ($response === false) {
    $error = curl_error($request);
    curl_close($request);
    throw new RuntimeException($error);
}
$status = curl_getinfo($request, CURLINFO_RESPONSE_CODE);
$contentType = (string) curl_getinfo($request, CURLINFO_CONTENT_TYPE);
curl_close($request);
if ($status >= 400) { throw new RuntimeException($response); }
$data = $status === 204 ? null
    : (str_contains($contentType, 'application/json')
        ? json_decode($response, true, flags: JSON_THROW_ON_ERROR) : $response);

Replace uppercase placeholders and sample values with your own data and company resource IDs. Keep the API key on a trusted server. Reuse an idempotency key only for the same logical request and payload.

Update Tax Profile

PUT
/2026-02-01/taxes/{taxId}.json
Required permissiontaxes:write

Path, query, and header parameters

taxIdstring· pathRequired
Tax profile ID.

Request Body

JSON
{
  "tax": {
    "name": "EU VAT 2026",
    "description": "Updated profile metadata",
    "percentage": 23,
    "default": true
  }
}
tax.namestring
Updated tax profile label.
tax.descriptionstring
Updated profile description.
tax.percentagenumber
Updated percentage value. Must be >= 0.
tax.defaultboolean
Update default profile flag.

Responses

Tax profile updated.

{
  "status": "success",
  "tax": {
    "id": "tax_001",
    "name": "EU VAT 2026",
    "percentage": 23
  }
}

Request examples

curl --request PUT 'https://api.hub.donutwork.com/2026-02-01/taxes/TAXID.json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
  "tax": {
    "name": "EU VAT 2026",
    "description": "Updated profile metadata",
    "percentage": 23,
    "default": true
  }
}'
const response = await fetch('https://api.hub.donutwork.com/2026-02-01/taxes/TAXID.json', {
  method: 'PUT',
  headers: {
    Authorization: 'Bearer ' + process.env.DONUTWORK_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "tax": {
      "name": "EU VAT 2026",
      "description": "Updated profile metadata",
      "percentage": 23,
      "default": true
    }
  }),
});
const requestId = response.headers.get('x-request-id');
if (!response.ok) {
  const error = await response.text();
  throw new Error(`${response.status} ${error} [${requestId}]`);
}
const contentType = response.headers.get('content-type') ?? '';
const data = response.status === 204 ? null
  : contentType.includes('application/json') ? await response.json()
  : await response.text();
$request = curl_init('https://api.hub.donutwork.com/2026-02-01/taxes/TAXID.json');
curl_setopt_array($request, [
    CURLOPT_CUSTOMREQUEST => 'PUT',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('DONUTWORK_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => '{
  "tax": {
    "name": "EU VAT 2026",
    "description": "Updated profile metadata",
    "percentage": 23,
    "default": true
  }
}',
]);
$response = curl_exec($request);
if ($response === false) {
    $error = curl_error($request);
    curl_close($request);
    throw new RuntimeException($error);
}
$status = curl_getinfo($request, CURLINFO_RESPONSE_CODE);
$contentType = (string) curl_getinfo($request, CURLINFO_CONTENT_TYPE);
curl_close($request);
if ($status >= 400) { throw new RuntimeException($response); }
$data = $status === 204 ? null
    : (str_contains($contentType, 'application/json')
        ? json_decode($response, true, flags: JSON_THROW_ON_ERROR) : $response);

Replace uppercase placeholders and sample values with your own data and company resource IDs. Keep the API key on a trusted server. Reuse an idempotency key only for the same logical request and payload.

Delete Tax Profile

DELETE
/2026-02-01/taxes/{taxId}.json
Required permissiontaxes:write

Path, query, and header parameters

taxIdstring· pathRequired
Tax profile ID.

Responses

Tax profile deleted.

{
  "status": "success",
  "tax": {
    "id": "tax_001",
    "deleted": true
  }
}

Tax profile not found.

{
  "error": "This tax profile does not exists"
}

Request examples

curl --request DELETE 'https://api.hub.donutwork.com/2026-02-01/taxes/TAXID.json' \
  --header 'Authorization: Bearer YOUR_API_KEY'
const response = await fetch('https://api.hub.donutwork.com/2026-02-01/taxes/TAXID.json', {
  method: 'DELETE',
  headers: {
    Authorization: 'Bearer ' + process.env.DONUTWORK_API_KEY,
  },
});
const requestId = response.headers.get('x-request-id');
if (!response.ok) {
  const error = await response.text();
  throw new Error(`${response.status} ${error} [${requestId}]`);
}
const contentType = response.headers.get('content-type') ?? '';
const data = response.status === 204 ? null
  : contentType.includes('application/json') ? await response.json()
  : await response.text();
$request = curl_init('https://api.hub.donutwork.com/2026-02-01/taxes/TAXID.json');
curl_setopt_array($request, [
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('DONUTWORK_API_KEY'),
    ],
]);
$response = curl_exec($request);
if ($response === false) {
    $error = curl_error($request);
    curl_close($request);
    throw new RuntimeException($error);
}
$status = curl_getinfo($request, CURLINFO_RESPONSE_CODE);
$contentType = (string) curl_getinfo($request, CURLINFO_CONTENT_TYPE);
curl_close($request);
if ($status >= 400) { throw new RuntimeException($response); }
$data = $status === 204 ? null
    : (str_contains($contentType, 'application/json')
        ? json_decode($response, true, flags: JSON_THROW_ON_ERROR) : $response);

Replace uppercase placeholders and sample values with your own data and company resource IDs. Keep the API key on a trusted server. Reuse an idempotency key only for the same logical request and payload.

On this page