Collect self-certifications

Collect a tax-residency self-certification from each account owner and check that it's valid, for CARF and DAC8 reporting.

Part of CARF & DAC8 Reporting.

The self-certification can come from either of two routes: the React SDK, where the account owner fills in the SELF-CERT questionnaire in your app, or the API, where you send a self-certification you hold from your backend. Digital platforms reporting seller income use a different questionnaire, the DPS; see Collect seller data.

Before you begin

1. Set up the account owner

The account owner's account_owner_type is INDIVIDUAL or ENTITY. Set its self_certification_classification, which is used to determine CARF and DAC8 reporting obligations, and its tax_residencies, one entry per country the account owner is resident in for tax:

curl -X PATCH $BASE_URL/v1/account-owners/usr_4d8a2e61 \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "self_certification_classification": "INDIVIDUAL",
    "tax_residencies": [
      { "country": "IT", "tin": "RNLSFO91H42F205X", "tin_type": "OTHER" }
    ]
  }'

A 200 returns the updated account owner in data. self_certification_classification takes the same values as classification on the self-certification in step 2.

If you collected the account owner's self-certification outside Taxbit and won't send it, set valid_self_certification_on_file to say whether a valid one is on file. Once a self-certification is on file in Taxbit, the field reflects that document's validation status instead of the value you set.

The other account owner fields are on Create account owners and accounts and Collect seller data.

2. Collect the self-certification

In your app, with the SDK

Render the questionnaire with questionnaire="SELF-CERT". Set data.accountHolder.isIndividual to true for an individual or false for an entity; an entity also needs selfCertificationAccountType (FINANCIAL_INSTITUTION, ACTIVE_NON_FINANCIAL_ENTITY, or PASSIVE_NON_FINANCIAL_ENTITY). The Questionnaire integration guide covers installing the SDK and rendering the questionnaire, entity flows included.

From your backend, with the API

Send the self-certification you hold. Here the account owner is an individual resident in Italy:

curl -X POST $BASE_URL/v1/account-owners/usr_4d8a2e61/tax-documentation-data/self-certification \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Sofia Rinaldi",
    "classification": "INDIVIDUAL",
    "permanent_address": {
      "first_line": "Via dei Glicini 18",
      "city": "Milan",
      "postal_code": "20144",
      "country": "IT"
    },
    "tax_residences": [
      { "country": "IT", "tin": "RNLSFO91H42F205X" }
    ],
    "date_of_birth": "1991-06-02",
    "city_of_birth": "Milan",
    "country_of_birth": "IT",
    "country_of_citizenship": "IT",
    "has_signed_and_certified": true,
    "signature_date": "2026-10-07T00:00:00.000Z"
  }'

A 201 returns the stored submission in data, with TINs masked. On the self-certification the residence list is tax_residences, without a tin_type; on the account owner it is tax_residencies.

The endpoint stores what you send and doesn't reject incomplete or inconsistent data. Taxbit validates the submission and reports problems through the status in step 3, so send the complete form, then read the status.

A few rules for the fields:

  • For a country where the account owner has no TIN, send the entry with tin_not_required set to true and a tin_not_required_reason of NOT_ISSUED, NOT_REQUIRED, or OTHER (with tin_not_required_reason_other for OTHER). Without the reason, the status reports an issue.
  • signature is the name signed on the form, and it requires has_signed_and_certified to be true. For an individual you can leave it out: Taxbit derives the signature from name.
  • Country fields take a two-letter ISO 3166-1 alpha-2 code, such as IT.

Entities. For an entity, classification is one of these values. NFE means non-financial entity.

GroupclassificationEntity
Financial institutionFINANCIAL_INSTITUTION_DEPOSITORY_INSTITUTIONDepository institution
Financial institutionFINANCIAL_INSTITUTION_CUSTODIAL_INSTITUTIONCustodial institution
Financial institutionFINANCIAL_INSTITUTION_INSURANCE_COMPANYInsurance company
Financial institutionFINANCIAL_INSTITUTION_NON_REPORTINGNon-reporting financial institution
Financial institutionFINANCIAL_INSTITUTION_INVESTMENT_ENTITY_MANAGEDManaged investment entity
Financial institutionFINANCIAL_INSTITUTION_INVESTMENT_ENTITY_OTHEROther investment entity
Active NFEACTIVE_NFE_GOVERNMENT_ENTITYGovernment entity
Active NFEACTIVE_NFE_CENTRAL_BANKCentral bank
Active NFEACTIVE_NFE_INTERNATIONAL_ORGANIZATIONInternational organization
Active NFEACTIVE_NFE_PUBLIC_CORPORATIONPublic corporation
Active NFEACTIVE_NFE_OTHERAny other active NFE
Passive NFEPASSIVE_NFEPassive NFE; needs at least one controlling person (below)

A PASSIVE_NFE self-certification must include at least one entry in controlling_persons, each with the person's name, role, and their own address, birth, and tax_residences details; without one, the status reports that "at least one controlling person must be provided for classification PASSIVE_NFE". The person who signs for the entity goes in signature, and their capacity in signature_capacity (OFFICER, EXECUTOR, or OTHER_CAPACITY, with signature_capacity_other for the last). The SDK's SELF-CERT questionnaire walks entities through all of this in your app.

3. Check the status

Read the account owner's tax documentation status:

curl $BASE_URL/v1/account-owners/usr_4d8a2e61/tax-documentation-status \
  -H "Authorization: Bearer $TOKEN"

For the submission above:

{
  "self_certification": {
    "data_collection_status": "COMPLETE",
    "tax_documentation_status": "VALID",
    "needs_resubmission": false,
    "issues": []
  }
}

self_certification reports on the latest self-certification:

  • data_collection_status is COMPLETE or INCOMPLETE: whether the required information has been collected.
  • tax_documentation_status is VALID when the most recently submitted self-certification has passed validation checks, or INVALID when it has issues or missing information to correct before it can be used for reporting.
  • needs_resubmission says whether to prompt the account owner to submit a new self-certification.
  • issues lists what needs fixing. Each issue has an issue_type, a status (OPEN, IN_REVIEW, or RESOLVED), and details, each naming a field and describing the problem.

A submission that left out tin_not_required_reason, for example, reads:

{
  "self_certification": {
    "data_collection_status": "INCOMPLETE",
    "tax_documentation_status": "INVALID",
    "needs_resubmission": true,
    "issues": [
      {
        "issue_type": "INCOMPLETE_DATA",
        "status": "OPEN",
        "created_at": "2026-10-07T20:11:52.741Z",
        "details": [
          {
            "field": "tax_residences.0.tin_not_required_reason",
            "description": "TIN-not-required reason must be provided when TIN is not required"
          }
        ]
      },
      {
        "issue_type": "INCONSISTENT_DATA",
        "status": "OPEN",
        "created_at": "2026-10-07T20:11:52.741Z",
        "details": [
          {
            "field": "tax_residences.0.tin_not_required_reason",
            "description": "must be provided"
          }
        ]
      }
    ]
  }
}

The issue types that apply to self-certifications are INCOMPLETE_DATA, INCONSISTENT_DATA, INCOMPLETE_ADDRESS, US_INDICIA, CHANGE_IN_CIRCUMSTANCES, CBI_RBI_CONFIRMATION, and INCOMPLETE_GIIN; the SDK component reference describes each.

Fixing issues. Correct the fields the issues name and submit the complete form again. The status reports on your latest submission: once it passes, the issues are gone and needs_resubmission is false.

On the account owner, valid_self_certification_on_file is the one-field summary. It is absent until a self-certification exists, then reflects the latest one's validation status, and is true once the status is VALID.

The stored data. GET /v1/account-owners/{id}/tax-documentation-data returns the stored self-certification under selfCertification, with document_type SELF_CERTIFICATION, is_individual, and, for an entity, self_certification_account_type. TINs are masked unless you pass unmask=true.

If the request fails

These apply to the self-certification POST.

  • 400. The request is malformed. Incomplete or inconsistent data doesn't return a 400; it shows up as issues in the status.
  • 401. The bearer token is missing, invalid, or expired. Request a new one and retry.
  • 404. No account owner has that id. Create it first, as Create account owners and accounts shows.
  • 429. Too many requests. Slow down and retry.

The Errors and rate limits page has every error shape, the rate limits, and which calls are safe to retry.

Parameters

Only the fields used above. "Required for this workflow" marks what a signed, complete self-certification needs; the status in step 3 lists any field a submission is still missing. The full schemas, with what the API itself requires, are in the Self-certification reference and the Account Owners reference.

POST /v1/account-owners/{id}/tax-documentation-data/self-certification

FieldTypeRequired for this workflowDescription
namestringOptionalThe account owner's legal name.
classificationstringOptionalINDIVIDUAL, or one of the entity values listed in step 2.
permanent_addressobjectOptionalfirst_line, second_line, city, state_or_province, postal_code, and country.
tax_residencesarrayRequiredOne entry per country of tax residence: country, and tin or tin_not_required with tin_not_required_reason.
date_of_birthstringOptionalISO 8601 date of birth.
city_of_birthstringOptionalCity of birth.
country_of_birthstringOptionalCountry of birth, as a two-letter code.
country_of_citizenshipstringOptionalCountry of citizenship, as a two-letter code.
controlling_personsarrayRequired for PASSIVE_NFEFor an entity: name, role, ownership_percentage, date_of_birth, city_of_birth, country_of_birth, country_of_citizenship, address, and tax_residences.
has_signed_and_certifiedbooleanRequiredWhether the account owner signed and certified the form.
signature_datestringOptionalISO 8601 timestamp of the signature.
signaturestringOptionalThe name signed. Requires has_signed_and_certified. Derived from name for an individual when left out.
signature_capacitystringOptionalFor an entity: OFFICER, EXECUTOR, or OTHER_CAPACITY.

PATCH /v1/account-owners/{id}

FieldTypeRequired for this workflowDescription
self_certification_classificationstringOptionalUsed to determine CARF and DAC8 reporting obligations. Same values as classification.
tax_residenciesarrayOptionalcountry, tin, and tin_type. Set to null to clear.
valid_self_certification_on_filebooleanOptionalWhether a valid self-certification is on file. Replaced by the latest self-certification's validation status once one is on file in Taxbit.

Where to go next