Référence de l'API
Version 2026-09-06. URL de base https://api.taxpio.com. Le contrat lisible par machine se trouve à /openapi.json.
Plateforme
GET /v1
Index de l'API : version, documentation et point de départ.
GET /v1/health
Disponibilité : la version déployée et sa base de données répondent.
GET /v1/me
L'espace de travail, l'application, l'environnement et les portées derrière la clé.
Calculs fiscaux
GET /v1/tax/programs
Les programmes de calcul et leurs données.
POST /v1/tax/calculations
Exécuter un calcul fiscal déterministe. Déterministe : la même demande renvoie toujours les mêmes lignes. Envoyez une Idempotency-Key pour sécuriser les nouvelles tentatives; une relecture porte `Idempotent-Replayed: true`.
| Paramètre | Emplacement | Requis | Type |
|---|---|---|---|
Idempotency-Key | header | non | string |
{
"type": "object",
"required": [
"jurisdiction",
"tax_year",
"inputs"
],
"properties": {
"jurisdiction": {
"type": "string",
"enum": [
"CA"
]
},
"program": {
"type": "string",
"enum": [
"T1",
"T2",
"1120",
"CT600",
"CIT"
],
"description": "Required for CA; defaults to the jurisdiction's program elsewhere."
},
"tax_year": {
"type": "integer",
"minimum": 2020,
"maximum": 2035
},
"inputs": {
"oneOf": [
{
"title": "CA/T1",
"type": "object",
"required": [
"facts"
],
"properties": {
"facts": {
"type": "object",
"description": "Personal facts: province, dateOfBirth, maritalStatus, eligibleDependant, …"
},
"slips": {
"type": "array",
"items": {
"type": "object",
"required": [
"kind"
],
"properties": {
"kind": {
"type": "string",
"enum": [
"T4",
"T4A",
"T4A_OAS",
"T4A_P",
"T4E",
"T5",
"T3",
"T5008",
"T2202",
"RRSP_RECEIPT",
"T2125",
"T776"
]
}
},
"additionalProperties": true
}
},
"claims": {
"type": "object",
"description": "rrspDeduction, professionalDues, childCareExpenses, otherEmploymentExpenses, medicalExpenses, charitableDonations, studentLoanInterest as decimal strings."
}
},
"description": "inputs = { facts, slips, claims } exactly as TaxPio's T1 rule package takes them: money as decimal strings in dollars, slips typed by kind (T4, T4A, T5, …)."
}
]
}
}
}GET /v1/tax/calculations
Énumérer les calculs, du plus récent au plus ancien.
| Paramètre | Emplacement | Requis | Type |
|---|---|---|---|
limit | query | non | integer |
cursor | query | non | string · Le next_cursor de la page précédente. |
GET /v1/tax/calculations/{calculationId}
Obtenir un calcul.
| Paramètre | Emplacement | Requis | Type |
|---|---|---|---|
calculationId | path | oui | string |
Bac à sable
GET /v1/sandbox/scenarios
Scénarios de bac à sable déterministes pour chaque programme et chaque résultat. Clés de bac à sable seulement (tp_test_…). Une clé réelle reçoit 403 SANDBOX_ONLY.
POST /v1/sandbox/scenarios/{scenarioId}/run
Exécuter un scénario comme un vrai calcul dans le bac à sable.
| Paramètre | Emplacement | Requis | Type |
|---|---|---|---|
scenarioId | path | oui | string |
Idempotency-Key | header | non | string |
POST /v1/sandbox/webhook-sink/{endpointId}
Un récepteur sur notre hôte qui vérifie la signature de TaxPio. Inscrivez un point de terminaison de bac à sable dont l'URL est https://api.taxpio.com/v1/sandbox/webhook-sink/{endpointId} (l'identifiant qui vous est renvoyé), et chaque livraison arrive ici, est vérifiée avec le secret de votre point de terminaison et apparaît dans la trace.
| Paramètre | Emplacement | Requis | Type |
|---|---|---|---|
endpointId | path | oui | string |
Taxpio-Signature | header | oui | string |
Webhooks
GET /v1/webhooks
Énumérer les points de terminaison de webhook.
POST /v1/webhooks
Inscrire un point de terminaison; le secret de signature est renvoyé une seule fois.
{
"type": "object",
"required": [
"url"
],
"properties": {
"url": {
"type": "string",
"format": "uri",
"description": "https only; a public host, or the sandbox sink on api.taxpio.com."
},
"description": {
"type": "string",
"maxLength": 500
},
"events": {
"type": "array",
"items": {
"type": "string",
"enum": [
"calculation.completed",
"key.revoked",
"webhook.test"
]
},
"description": "Defaults to every event."
}
}
}GET /v1/webhooks/{endpointId}
Obtenir un point de terminaison.
| Paramètre | Emplacement | Requis | Type |
|---|---|---|---|
endpointId | path | oui | string |
DELETE /v1/webhooks/{endpointId}
Supprimer un point de terminaison et ses livraisons.
| Paramètre | Emplacement | Requis | Type |
|---|---|---|---|
endpointId | path | oui | string |
POST /v1/webhooks/{endpointId}/test
Mettre en file une livraison webhook.test.
| Paramètre | Emplacement | Requis | Type |
|---|---|---|---|
endpointId | path | oui | string |
GET /v1/webhooks/{endpointId}/deliveries
Livraisons récentes à un point de terminaison.
| Paramètre | Emplacement | Requis | Type |
|---|---|---|---|
endpointId | path | oui | string |
limit | query | non | integer |
Connexions
GET /v1/connections
Connexions aux profils des clients.
| Paramètre | Emplacement | Requis | Type |
|---|---|---|---|
limit | query | non | integer |
cursor | query | non | string |
POST /v1/connections
Inviter un client à connecter un profil. TaxPio envoie un lien au client par courriel; il choisit lequel de ses profils connecter et quelles autorisations accorder. La connexion reste INVITED d'ici là, et l'une ou l'autre partie peut la révoquer.
{
"type": "object",
"required": [
"client_email",
"system_name"
],
"properties": {
"client_email": {
"type": "string",
"format": "email"
},
"client_name": {
"type": "string"
},
"category": {
"type": "string",
"enum": [
"ACCOUNTING",
"ERP",
"ECOMMERCE",
"PAYROLL",
"PAYMENTS",
"CUSTOM"
]
},
"system_name": {
"type": "string",
"description": "The system the records come from, e.g. QuickBooks Online, Shopify, Gusto."
},
"permissions": {
"type": "array",
"items": {
"type": "string",
"enum": [
"records.import",
"records.read",
"documents.write"
]
},
"description": "Defaults to all three."
}
}
}GET /v1/connections/{connectionId}
Obtenir une connexion.
| Paramètre | Emplacement | Requis | Type |
|---|---|---|---|
connectionId | path | oui | string |
DELETE /v1/connections/{connectionId}
Mettre fin à une connexion.
| Paramètre | Emplacement | Requis | Type |
|---|---|---|---|
connectionId | path | oui | string |
POST /v1/connections/{connectionId}/records
Envoyer jusqu'à 500 dossiers dans le profil connecté. Chaque dossier est identifié par votre external_id; une répétition du même identifiant est comptée comme doublon et jamais écrite deux fois. Les montants sont des chaînes décimales signées dans la devise du profil : négatives pour l'argent sortant, positives pour l'argent entrant. Les dossiers arrivent comme opérations non révisées avec des suggestions d'association de reçus, exactement comme une synchronisation bancaire.
| Paramètre | Emplacement | Requis | Type |
|---|---|---|---|
connectionId | path | oui | string |
Idempotency-Key | header | non | string |
{
"type": "object",
"required": [
"records"
],
"properties": {
"records": {
"type": "array",
"maxItems": 500,
"items": {
"$ref": "#/components/schemas/RecordInput"
}
}
}
}GET /v1/connections/{connectionId}/records
Dossiers envoyés par cette connexion.
| Paramètre | Emplacement | Requis | Type |
|---|---|---|---|
connectionId | path | oui | string |
limit | query | non | integer |
cursor | query | non | string |
POST /v1/connections/{connectionId}/documents
Téléverser un document dans le profil connecté. multipart/form-data avec le fichier (PDF, JPEG, PNG ou WebP, jusqu'à 15 Mo) et des métadonnées facultatives; la chaîne de traitement du coffre et les suggestions de l'IA s'exécutent comme pour toute saisie.
| Paramètre | Emplacement | Requis | Type |
|---|---|---|---|
connectionId | path | oui | string |
Idempotency-Key | header | non | string |
Utilisation et crédits
GET /v1/usage
Demandes par jour et par opération.
| Paramètre | Emplacement | Requis | Type |
|---|---|---|---|
from | query | non | string |
to | query | non | string |
GET /v1/credits
Solde de crédits et mouvements récents. Les crédits paient les actions de production facturables avec des clés réelles et sont consommés une fois par demande (l'ID de la demande est la clé d'idempotence). Un appel réel qui exige plus de crédits que l'espace de travail n'en détient répond 402 CREDITS_REQUIRED. Le bac à sable n'est jamais facturé.
Schémas
{
"type": "object",
"required": [
"error",
"code",
"requestId"
],
"properties": {
"error": {
"type": "string",
"description": "A sentence a person can read."
},
"code": {
"type": "string",
"enum": [
"BAD_REQUEST",
"UNAUTHENTICATED",
"PAYMENT_REQUIRED",
"FORBIDDEN",
"NOT_FOUND",
"METHOD_NOT_ALLOWED",
"NOT_ACCEPTABLE",
"REQUEST_TIMEOUT",
"CONFLICT",
"GONE",
"PAYLOAD_TOO_LARGE",
"UNSUPPORTED_MEDIA_TYPE",
"VALIDATION_FAILED",
"LOCKED",
"PRECONDITION_REQUIRED",
"RATE_LIMITED",
"INTERNAL",
"NOT_IMPLEMENTED",
"UNAVAILABLE",
"TIMEOUT",
"ORIGIN_REQUIRED",
"PASSKEY_REQUIRED",
"PASSKEY_ENROLLMENT_REQUIRED",
"RECENT_MFA_REQUIRED",
"RECENT_AUTHENTICATION_REQUIRED",
"ACCOUNT_PASSWORD_REQUIRED",
"EMAIL_VERIFICATION_REQUIRED",
"VERIFICATION_DELIVERY_FAILED",
"RESOURCE_ROUTE_UNAVAILABLE",
"MALWARE_DETECTED",
"NONDETERMINISTIC_PROVIDER_RETRY",
"CREDITS_REQUIRED",
"API_KEY_MISSING",
"API_KEY_INVALID",
"API_KEY_REVOKED",
"API_KEY_EXPIRED",
"WORKSPACE_SUSPENDED",
"APPLICATION_ARCHIVED",
"SCOPE_REQUIRED",
"PRODUCTION_REVIEW_REQUIRED",
"IDEMPOTENCY_KEY_INVALID",
"IDEMPOTENCY_KEY_REUSED",
"IDEMPOTENCY_KEY_IN_PROGRESS",
"BODY_INVALID",
"UNSUPPORTED_PROGRAM",
"SANDBOX_ONLY",
"CONNECTION_PENDING",
"CONNECTION_REVOKED",
"CONNECTION_PERMISSION_REQUIRED",
"LIVE_ONLY",
"WEBHOOK_SIGNATURE_INVALID"
],
"description": "What a client branches on."
},
"requestId": {
"type": "string",
"description": "Quote it to support; it is also the x-request-id response header."
},
"docs_url": {
"type": "string",
"format": "uri"
},
"problems": {
"type": "array",
"items": {
"type": "object",
"properties": {
"field": {
"type": "string"
},
"message": {
"type": "string"
}
}
}
}
}
}{
"type": "object",
"required": [
"id",
"object",
"environment",
"jurisdiction",
"program",
"tax_year",
"rule_package",
"currency",
"scope",
"reasons",
"notes",
"lines",
"inputs",
"input_hash",
"created_at"
],
"properties": {
"id": {
"type": "string",
"pattern": "^calc_[A-Za-z0-9]{20,32}$"
},
"object": {
"type": "string",
"enum": [
"tax.calculation"
]
},
"environment": {
"type": "string",
"enum": [
"live",
"sandbox"
]
},
"jurisdiction": {
"type": "string",
"enum": [
"CA"
]
},
"program": {
"type": "string",
"enum": [
"T1",
"T2"
]
},
"tax_year": {
"type": "integer"
},
"rule_package": {
"type": "string",
"description": "The versioned rule package that produced the answer."
},
"currency": {
"type": "string"
},
"scope": {
"type": "string",
"enum": [
"IN_SCOPE",
"OUT_OF_SCOPE",
"INCOMPLETE"
],
"description": "OUT_OF_SCOPE: the inputs describe a case the package refuses, with reasons. INCOMPLETE: CA/T1 with blocking issues."
},
"reasons": {
"type": "array",
"items": {
"type": "string"
}
},
"notes": {
"type": "array",
"items": {
"type": "string"
}
},
"lines": {
"type": "array",
"items": {
"type": "object",
"required": [
"key",
"label"
],
"properties": {
"key": {
"type": "string"
},
"label": {
"type": "string"
},
"amount_minor": {
"type": "integer",
"description": "Minor units (cents, pence, kobo) for preview programs."
},
"amount": {
"type": "string",
"description": "Decimal string in the currency for CA/T1."
},
"text": {
"type": "string"
}
}
}
},
"summary": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"issues": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"severity": {
"type": "string"
},
"message": {
"type": "string"
},
"fix_action": {
"type": "string"
}
}
}
},
"inputs": {
"type": "object"
},
"input_hash": {
"type": "string"
},
"created_at": {
"type": "string",
"format": "date-time"
}
}
}{
"type": "object",
"properties": {
"id": {
"type": "string"
},
"object": {
"type": "string",
"enum": [
"webhook_endpoint"
]
},
"environment": {
"type": "string",
"enum": [
"live",
"sandbox"
]
},
"url": {
"type": "string"
},
"description": {
"type": "string",
"nullable": true
},
"events": {
"type": "array",
"items": {
"type": "string"
}
},
"status": {
"type": "string",
"enum": [
"ACTIVE",
"DISABLED"
]
},
"secret_prefix": {
"type": "string"
},
"consecutive_failures": {
"type": "integer"
},
"last_delivery_at": {
"type": "string",
"nullable": true
},
"created_at": {
"type": "string"
}
}
}{
"type": "object",
"properties": {
"id": {
"type": "string"
},
"object": {
"type": "string",
"enum": [
"webhook_delivery"
]
},
"endpoint_id": {
"type": "string"
},
"event_id": {
"type": "string"
},
"event_type": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"PENDING",
"DELIVERED",
"FAILED",
"DEAD"
]
},
"attempts": {
"type": "integer"
},
"next_attempt_at": {
"type": "string",
"nullable": true
},
"last_status": {
"type": "integer",
"nullable": true
},
"last_error": {
"type": "string",
"nullable": true
},
"delivered_at": {
"type": "string",
"nullable": true
},
"created_at": {
"type": "string"
}
}
}{
"type": "object",
"description": "The body of every webhook delivery, signed with `Taxpio-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\">`.",
"properties": {
"id": {
"type": "string"
},
"object": {
"type": "string",
"enum": [
"event"
]
},
"type": {
"type": "string",
"enum": [
"calculation.completed",
"key.revoked",
"webhook.test"
]
},
"created": {
"type": "string"
},
"environment": {
"type": "string"
},
"workspace_id": {
"type": "string"
},
"data": {
"type": "object"
},
"attempt": {
"type": "integer"
}
}
}{
"type": "object",
"properties": {
"id": {
"type": "string"
},
"object": {
"type": "string",
"enum": [
"connection"
]
},
"environment": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"INVITED",
"ACTIVE",
"REVOKED",
"DECLINED",
"EXPIRED"
]
},
"category": {
"type": "string"
},
"system_name": {
"type": "string"
},
"permissions": {
"type": "array",
"items": {
"type": "string"
}
},
"client_email": {
"type": "string",
"nullable": true
},
"client_name": {
"type": "string",
"nullable": true
},
"profile": {
"type": "object",
"nullable": true,
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
}
}
},
"granted_at": {
"type": "string",
"nullable": true
},
"revoked_at": {
"type": "string",
"nullable": true
},
"expires_at": {
"type": "string",
"nullable": true
},
"last_import_at": {
"type": "string",
"nullable": true
},
"records_imported": {
"type": "integer"
},
"documents_imported": {
"type": "integer"
},
"created_at": {
"type": "string"
}
}
}{
"type": "object",
"required": [
"external_id",
"occurred_at",
"description",
"amount"
],
"properties": {
"external_id": {
"type": "string",
"maxLength": 120,
"description": "Your stable id for the record."
},
"occurred_at": {
"type": "string",
"format": "date"
},
"description": {
"type": "string",
"maxLength": 240
},
"amount": {
"type": "string",
"description": "Signed decimal string, at most two decimals, non-zero."
},
"counterparty": {
"type": "string",
"maxLength": 200,
"description": "Folded into the description when the description does not already name it; TaxPio's own counterparty is set when the owner reviews the record."
},
"category": {
"type": "string",
"maxLength": 80,
"description": "Kept as a hint in the import's audit trail; TaxPio's category and tax treatment are set when the owner reviews the record."
}
}
}{
"type": "object",
"properties": {
"object": {
"type": "string",
"enum": [
"principal"
]
},
"workspace": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
}
}
},
"application": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
}
}
},
"environment": {
"type": "string",
"enum": [
"live",
"sandbox"
]
},
"scopes": {
"type": "array",
"items": {
"type": "string",
"enum": [
"calculations:read",
"calculations:write",
"connections:manage",
"records:import",
"records:read",
"documents:read",
"documents:write",
"webhooks:manage",
"usage:read"
]
}
},
"rate_limit_per_minute": {
"type": "integer"
}
}
}