DOCUMENTATION DE L'API

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.

Aucune portée

Réponses : 200 L'index.

GET /v1/health

Disponibilité : la version déployée et sa base de données répondent.

Aucune portée

Réponses : 200 En bon état. · 503 La base de données ne répond pas.

GET /v1/me

L'espace de travail, l'application, l'environnement et les portées derrière la clé.

Aucune portée

Réponses : 200 Le mandant. · 401 401 · 403 403 · 429 429

Calculs fiscaux

GET /v1/tax/programs

Les programmes de calcul et leurs données.

Aucune portée

Réponses : 200 Les programmes. · 401 401 · 429 429

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`.

Portée calculations:write · accepte Idempotency-Key

ParamètreEmplacementRequisType
Idempotency-Keyheadernonstring
Schéma du corps de la demande
{
  "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, …)."
        }
      ]
    }
  }
}

Réponses : 201 Le calcul. · 400 400 · 401 401 · 403 403 · 409 409 · 413 413 · 415 415 · 422 422 · 429 429

GET /v1/tax/calculations

Énumérer les calculs, du plus récent au plus ancien.

Portée calculations:read

ParamètreEmplacementRequisType
limitquerynoninteger
cursorquerynonstring · Le next_cursor de la page précédente.

Réponses : 200 Une page de calculs. · 400 400 · 401 401 · 403 403 · 429 429

GET /v1/tax/calculations/{calculationId}

Obtenir un calcul.

Portée calculations:read

ParamètreEmplacementRequisType
calculationIdpathouistring

Réponses : 200 Le calcul. · 401 401 · 403 403 · 404 404 · 429 429

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.

Aucune portée

Réponses : 200 Les scénarios. · 401 401 · 403 403 · 429 429

POST /v1/sandbox/scenarios/{scenarioId}/run

Exécuter un scénario comme un vrai calcul dans le bac à sable.

Portée calculations:write · accepte Idempotency-Key

ParamètreEmplacementRequisType
scenarioIdpathouistring
Idempotency-Keyheadernonstring

Réponses : 201 Le calcul, avec le scénario dont il provient. · 401 401 · 403 403 · 404 404 · 409 409 · 429 429

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.

Aucune portée

ParamètreEmplacementRequisType
endpointIdpathouistring
Taxpio-Signatureheaderouistring

Réponses : 200 Reçue et vérifiée. · 401 401 · 413 413

Webhooks

GET /v1/webhooks

Énumérer les points de terminaison de webhook.

Portée webhooks:manage

Réponses : 200 Les points de terminaison. · 401 401 · 403 403 · 429 429

POST /v1/webhooks

Inscrire un point de terminaison; le secret de signature est renvoyé une seule fois.

Portée webhooks:manage · accepte Idempotency-Key

Schéma du corps de la demande
{
  "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."
    }
  }
}

Réponses : 201 Le point de terminaison avec son secret (affiché une seule fois). · 401 401 · 403 403 · 409 409 · 422 422 · 429 429

GET /v1/webhooks/{endpointId}

Obtenir un point de terminaison.

Portée webhooks:manage

ParamètreEmplacementRequisType
endpointIdpathouistring

Réponses : 200 Le point de terminaison. · 401 401 · 403 403 · 404 404 · 429 429

DELETE /v1/webhooks/{endpointId}

Supprimer un point de terminaison et ses livraisons.

Portée webhooks:manage

ParamètreEmplacementRequisType
endpointIdpathouistring

Réponses : 200 Supprimé. · 401 401 · 403 403 · 404 404 · 429 429

POST /v1/webhooks/{endpointId}/test

Mettre en file une livraison webhook.test.

Portée webhooks:manage

ParamètreEmplacementRequisType
endpointIdpathouistring

Réponses : 202 En file; le processus livre en moins d'une demi-minute. · 401 401 · 403 403 · 404 404 · 409 409 · 429 429

GET /v1/webhooks/{endpointId}/deliveries

Livraisons récentes à un point de terminaison.

Portée webhooks:manage

ParamètreEmplacementRequisType
endpointIdpathouistring
limitquerynoninteger

Réponses : 200 Les livraisons. · 401 401 · 403 403 · 404 404 · 429 429

Connexions

GET /v1/connections

Connexions aux profils des clients.

Portée connections:manage

ParamètreEmplacementRequisType
limitquerynoninteger
cursorquerynonstring

Réponses : 200 Une page de connexions. · 400 400 · 401 401 · 403 403 · 429 429

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.

Portée connections:manage · accepte Idempotency-Key

Schéma du corps de la demande
{
  "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."
    }
  }
}

Réponses : 201 La connexion invitée. · 401 401 · 403 403 · 422 422 · 429 429

GET /v1/connections/{connectionId}

Obtenir une connexion.

Portée connections:manage

ParamètreEmplacementRequisType
connectionIdpathouistring

Réponses : 200 La connexion. · 401 401 · 403 403 · 404 404 · 429 429

DELETE /v1/connections/{connectionId}

Mettre fin à une connexion.

Portée connections:manage

ParamètreEmplacementRequisType
connectionIdpathouistring

Réponses : 200 Révoquée. · 401 401 · 403 403 · 404 404 · 429 429

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.

Portée records:import · accepte Idempotency-Key

ParamètreEmplacementRequisType
connectionIdpathouistring
Idempotency-Keyheadernonstring
Schéma du corps de la demande
{
  "type": "object",
  "required": [
    "records"
  ],
  "properties": {
    "records": {
      "type": "array",
      "maxItems": 500,
      "items": {
        "$ref": "#/components/schemas/RecordInput"
      }
    }
  }
}

Réponses : 201 Le résumé de l'importation : inserted, duplicates, suggestions, affected_tax_years. · 401 401 · 403 403 · 404 404 · 409 409 · 422 422 · 429 429

GET /v1/connections/{connectionId}/records

Dossiers envoyés par cette connexion.

Portée records:read

ParamètreEmplacementRequisType
connectionIdpathouistring
limitquerynoninteger
cursorquerynonstring

Réponses : 200 Une page de dossiers. · 400 400 · 401 401 · 403 403 · 404 404 · 409 409 · 429 429

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.

Portée documents:write

ParamètreEmplacementRequisType
connectionIdpathouistring
Idempotency-Keyheadernonstring

Réponses : 201 Le document enregistré. · 401 401 · 403 403 · 404 404 · 409 409 · 413 413 · 422 422 · 429 429

Utilisation et crédits

GET /v1/usage

Demandes par jour et par opération.

Portée usage:read

ParamètreEmplacementRequisType
fromquerynonstring
toquerynonstring

Réponses : 200 Utilisation pour la période (au plus 92 jours). · 400 400 · 401 401 · 403 403 · 429 429

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é.

Portée usage:read

Réponses : 200 Le solde. · 401 401 · 403 403 · 429 429

Schémas

Error
{
  "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"
          }
        }
      }
    }
  }
}
Calculation
{
  "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"
    }
  }
}
WebhookEndpoint
{
  "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"
    }
  }
}
WebhookDelivery
{
  "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"
    }
  }
}
Event
{
  "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"
    }
  }
}
Connection
{
  "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"
    }
  }
}
RecordInput
{
  "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."
    }
  }
}
Principal
{
  "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"
    }
  }
}