Fetch Tax
The Fetch Tax endpoint retrieves detailed information about a specific tax configuration by its unique identifier. This endpoint provides complete tax details including associated applications and metadata.
Endpoint DetailsCopied!
-
URL:
/api/v0/taxes/{id}
-
Method:
GET
-
Authentication: Required (API Key Authentication)
-
Content-Type:
application/json
AuthenticationCopied!
This endpoint requires API key authentication using:
-
x-client-key
: Your API client key -
x-client-secret
: Your API client secret
Path ParametersCopied!
Required Parameters
Parameter |
Type |
Description |
Validation |
---|---|---|---|
|
|
Unique identifier of the tax to retrieve |
Must be a valid UUID v4 |
Request ExamplesCopied!
Basic Request
curl -X GET https://api.devdraft.com/api/v0/taxes/123e4567-e89b-12d3-a456-426614174000 \
-H "x-client-key: your-client-key" \
-H "x-client-secret: your-client-secret"
JavaScript/Fetch
const taxId = "123e4567-e89b-12d3-a456-426614174000";
const response = await fetch(`/api/v0/taxes/${taxId}`, {
headers: {
'x-client-key': 'your-client-key',
'x-client-secret': 'your-client-secret'
}
});
const tax = await response.json();
ResponseCopied!
Success Response (200 OK)
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "VAT",
"description": "Value Added Tax for European Union transactions",
"business_id": "456e7890-e89b-12d3-a456-426614174001",
"percentage": 20.0,
"active": true,
"created_at": "2024-01-15T10:30:00.000Z",
"updated_at": "2024-01-20T14:45:00.000Z",
"apps": [
{
"id": "789e0123-e89b-12d3-a456-426614174002",
"business_id": "456e7890-e89b-12d3-a456-426614174001",
"app_name": "eu-store",
"display_name": "European Store",
"environment": "PRODUCTION",
"stage": "PRODUCTION",
"timezone": "Europe/London",
"created_at": "2024-01-10T08:00:00.000Z",
"updated_at": "2024-01-10T08:00:00.000Z"
},
{
"id": "890e1234-e89b-12d3-a456-426614174003",
"business_id": "456e7890-e89b-12d3-a456-426614174001",
"app_name": "uk-marketplace",
"display_name": "UK Marketplace",
"environment": "PRODUCTION",
"stage": "PRODUCTION",
"timezone": "Europe/London",
"created_at": "2024-01-05T12:00:00.000Z",
"updated_at": "2024-01-05T12:00:00.000Z"
}
]
}
Error Responses
401 Unauthorized - Missing Authentication
{
"statusCode": 401,
"message": "Application not authenticated",
"error": "Unauthorized"
}
401 Unauthorized - Access Denied
{
"statusCode": 401,
"message": "Access denied to this tax",
"error": "Unauthorized"
}
404 Not Found
{
"statusCode": 404,
"message": "Tax not found",
"error": "Not Found"
}
400 Bad Request - Invalid UUID
{
"statusCode": 400,
"message": "Validation failed (uuid v4 is expected)",
"error": "Bad Request"
}
Response FieldsCopied!
Tax Object Fields
Field |
Type |
Description |
---|---|---|
|
|
Unique identifier for the tax (UUID v4) |
|
|
Tax name (e.g., "VAT", "Sales Tax", "GST") |
|
|
Detailed description of the tax |
|
|
ID of the business this tax belongs to |
|
|
Tax percentage rate (e.g., 20.0 for 20%) |
|
|
Whether the tax is currently active and can be used |
|
|
ISO 8601 timestamp when the tax was created |
|
|
ISO 8601 timestamp when the tax was last updated |
|
|
Array of applications that have access to this tax |
App Object Fields
Field |
Type |
Description |
---|---|---|
|
|
Unique identifier for the application |
|
|
ID of the business this app belongs to |
|
|
Internal application name (kebab-case) |
|
|
Human-readable application name |
|
|
Application environment (always "PRODUCTION") |
|
|
Application stage (always "PRODUCTION") |
|
|
Application timezone (e.g., "UTC", "America/New_York") |
|
|
ISO 8601 timestamp when the app was created |
|
|
ISO 8601 timestamp when the app was last updated |
Access ControlCopied!
Application-Scoped Access
-
You can only retrieve taxes that are associated with your authenticated application
-
If a tax is not associated with your app, you'll receive a
401 Unauthorized
response -
This ensures data isolation between different applications
Business-Level Isolation
-
Taxes are scoped to the business level
-
Applications from different businesses cannot access each other's taxes
-
The system automatically enforces this boundary
Use CasesCopied!
1. Tax Configuration Display
Retrieve tax details for configuration screens:
async function displayTaxConfiguration(taxId) {
try {
const tax = await fetchTax(taxId);
return {
name: tax.name,
rate: `${tax.percentage}%`,
status: tax.active ? 'Active' : 'Inactive',
description: tax.description || 'No description provided',
applications: tax.apps.map(app => app.display_name).join(', '),
lastUpdated: new Date(tax.updated_at).toLocaleDateString()
};
} catch (error) {
console.error('Failed to load tax configuration:', error);
throw error;
}
}
2. Invoice Tax Validation
Verify tax details before applying to invoices:
async function validateTaxForInvoice(taxId) {
const tax = await fetchTax(taxId);
if (!tax.active) {
throw new Error(`Tax "${tax.name}" is inactive and cannot be used`);
}
return {
id: tax.id,
name: tax.name,
percentage: tax.percentage
};
}
3. Tax Rate Calculation
Get tax rate for price calculations:
async function calculateTaxAmount(taxId, baseAmount) {
const tax = await fetchTax(taxId);
if (!tax.active) {
throw new Error('Cannot calculate with inactive tax');
}
const taxAmount = (baseAmount * tax.percentage) / 100;
return {
baseAmount,
taxRate: tax.percentage,
taxAmount,
totalAmount: baseAmount + taxAmount,
taxName: tax.name
};
}
4. Tax History and Audit
Track tax configuration changes:
async function getTaxAuditInfo(taxId) {
const tax = await fetchTax(taxId);
return {
taxId: tax.id,
currentRate: tax.percentage,
status: tax.active,
createdDate: tax.created_at,
lastModified: tax.updated_at,
associatedApps: tax.apps.length,
businessId: tax.business_id
};
}
Integration ExamplesCopied!
React Component
import React, { useState, useEffect } from 'react';
function TaxDetails({ taxId }) {
const [tax, setTax] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function loadTax() {
try {
setLoading(true);
const response = await fetch(`/api/v0/taxes/${taxId}`, {
headers: {
'x-client-key': process.env.REACT_APP_CLIENT_KEY,
'x-client-secret': process.env.REACT_APP_CLIENT_SECRET
}
});
if (!response.ok) {
throw new Error(`Failed to load tax: ${response.statusText}`);
}
const taxData = await response.json();
setTax(taxData);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
}
if (taxId) {
loadTax();
}
}, [taxId]);
if (loading) return <div>Loading tax details...</div>;
if (error) return <div>Error: {error}</div>;
if (!tax) return <div>Tax not found</div>;
return (
<div className="tax-details">
<h3>{tax.name}</h3>
<p><strong>Rate:</strong> {tax.percentage}%</p>
<p><strong>Status:</strong> {tax.active ? 'Active' : 'Inactive'}</p>
{tax.description && (
<p><strong>Description:</strong> {tax.description}</p>
)}
<p><strong>Applications:</strong> {tax.apps.length}</p>
<ul>
{tax.apps.map(app => (
<li key={app.id}>{app.display_name}</li>
))}
</ul>
</div>
);
}
Python
import requests
from typing import Optional, Dict, Any
class TaxService:
def __init__(self, client_key: str, client_secret: str, base_url: str):
self.client_key = client_key
self.client_secret = client_secret
self.base_url = base_url
def get_tax(self, tax_id: str) -> Optional[Dict[Any, Any]]:
"""Fetch a tax by ID"""
headers = {
'x-client-key': self.client_key,
'x-client-secret': self.client_secret
}
response = requests.get(
f"{self.base_url}/api/v0/taxes/{tax_id}",
headers=headers
)
if response.status_code == 200:
return response.json()
elif response.status_code == 404:
return None
else:
response.raise_for_status()
def calculate_tax(self, tax_id: str, amount: float) -> Dict[str, Any]:
"""Calculate tax amount for a given base amount"""
tax = self.get_tax(tax_id)
if not tax:
raise ValueError(f"Tax with ID {tax_id} not found")
if not tax['active']:
raise ValueError(f"Tax '{tax['name']}' is inactive")
tax_amount = (amount * tax['percentage']) / 100
return {
'base_amount': amount,
'tax_rate': tax['percentage'],
'tax_amount': tax_amount,
'total_amount': amount + tax_amount,
'tax_name': tax['name']
}
# Usage
tax_service = TaxService('your-key', 'your-secret', 'https://api.devdraft.com')
tax = tax_service.get_tax('123e4567-e89b-12d3-a456-426614174000')
if tax:
print(f"Tax: {tax['name']} ({tax['percentage']}%)")
calculation = tax_service.calculate_tax(tax['id'], 100.00)
print(f"Tax on $100: ${calculation['tax_amount']:.2f}")
Node.js/Express
const express = require('express');
const axios = require('axios');
class TaxService {
constructor(clientKey, clientSecret, baseUrl) {
this.clientKey = clientKey;
this.clientSecret = clientSecret;
this.baseUrl = baseUrl;
}
async getTax(taxId) {
try {
const response = await axios.get(
`${this.baseUrl}/api/v0/taxes/${taxId}`,
{
headers: {
'x-client-key': this.clientKey,
'x-client-secret': this.clientSecret
}
}
);
return response.data;
} catch (error) {
if (error.response?.status === 404) {
return null;
}
throw error;
}
}
async validateTaxForUse(taxId) {
const tax = await this.getTax(taxId);
if (!tax) {
throw new Error(`Tax with ID ${taxId} not found`);
}
if (!tax.active) {
throw new Error(`Tax "${tax.name}" is inactive and cannot be used`);
}
return tax;
}
}
// Express route example
const app = express();
const taxService = new TaxService(
process.env.CLIENT_KEY,
process.env.CLIENT_SECRET,
'https://api.devdraft.com'
);
app.get('/taxes/:id', async (req, res) => {
try {
const tax = await taxService.getTax(req.params.id);
if (!tax) {
return res.status(404).json({ error: 'Tax not found' });
}
res.json(tax);
} catch (error) {
console.error('Error fetching tax:', error);
res.status(500).json({ error: 'Internal server error' });
}
});
Rate LimitingCopied!
This endpoint is subject to the standard API rate limits:
-
Production: 1000 requests per hour per API key
-
Development: 100 requests per hour per API key
Best PracticesCopied!
1. Error Handling
Implement comprehensive error handling:
async function safeFetchTax(taxId) {
try {
const tax = await fetchTax(taxId);
return { success: true, data: tax };
} catch (error) {
if (error.status === 404) {
return { success: false, error: 'Tax not found' };
} else if (error.status === 401) {
return { success: false, error: 'Access denied' };
} else {
return { success: false, error: 'Network error' };
}
}
}
2. Caching
Cache frequently accessed tax data:
const taxCache = new Map();
const CACHE_TTL = 30 * 60 * 1000; // 30 minutes
async function getCachedTax(taxId) {
const cached = taxCache.get(taxId);
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
return cached.data;
}
const tax = await fetchTax(taxId);
taxCache.set(taxId, {
data: tax,
timestamp: Date.now()
});
return tax;
}
3. Input Validation
Validate tax ID format before API calls:
function isValidUUID(str) {
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
return uuidRegex.test(str);
}
async function fetchTaxSafely(taxId) {
if (!isValidUUID(taxId)) {
throw new Error('Invalid tax ID format');
}
return await fetchTax(taxId);
}
4. Status Checking
Always verify tax status before use:
function ensureTaxIsUsable(tax) {
if (!tax.active) {
throw new Error(`Tax "${tax.name}" is inactive`);
}
// Additional business logic checks
if (tax.percentage < 0) {
throw new Error('Invalid tax rate');
}
return true;
}
Security ConsiderationsCopied!
-
Access Control: Only applications associated with the tax can retrieve it
-
Data Isolation: Business-level isolation prevents cross-business access
-
Input Validation: UUID validation prevents injection attacks
-
Rate Limiting: Prevents abuse and ensures fair usage
-
Audit Trail: Consider logging tax access for compliance purposes