Create certify
Signs the caller org's certification — Form W-9 Part II, Form W-8BEN Part III or Form W-8BEN-E Part XXX — through /v1/legal's e-signature.
POST /v1/tax/profile/certify
| Address | https://api.hanzo.ai/v1/tax/profile/certify |
| Method | POST |
| Operation | post_tax_profile_certify |
| Auth | Authorization: Bearer $HANZO_API_KEY |
Signs the caller org's certification — Form W-9 Part II, Form W-8BEN Part III or Form W-8BEN-E Part XXX — through /v1/legal's e-signature. The org's own admins only, and the admin is the signer: a SuperAdmin acting inside the org is not a person who can certify for it.
The first call renders the certification — the IRS's own certification text over
this profile's facts, every number truncated — as a /v1/legal document and opens
its signature request with the calling admin as signer; the answer is pending with
the document id. The signer completes it where every /v1/legal signature is
completed (POST /v1/legal/documents/{id}/sign/complete). Calling this again then
asks legal whether the document is signed and by whom: signed by the signer, the
profile is recorded certified; not yet signed, it answers pending again; signed
by anyone else — another member, a key — or voided, it is not the signer's
certification, and a fresh request is opened in its place.
A certification covers one profile version: writing any fact on the form afterwards voids it. A certified W-8 is valid through the last day of the third calendar year after the year it was signed (Instructions for Form W-8BEN and W-8BEN-E, Rev. 10-2021); certifying it again after that renews it. It is not a statement that a TIN matches IRS records — that is IRS TIN Matching, which only a payer enrolled in IRS e-Services can run.
Request
The document declares no body for POST /v1/tax/profile/certify. The handler is typed in cloud but its shape is not yet emitted, so the fields are not listed here — ask MCP's describe for post_tax_profile_certify, which answers from the running route.
Response
| Status | Body | Meaning |
|---|---|---|
200 | tax.Profile | ok |
default | problem-details | refused |
200 body — 49 fields.
| Field | In | Type | Always | Description |
|---|---|---|---|---|
address | body | tax.Address | — | |
address.city | body | string | — | City is the city or town. |
address.country | body | string | — | Country is ISO 3166-1 alpha-2; "US" when absent. |
address.line1 | body | string | — | Line1 is the number, street, and apartment or suite. |
address.line2 | body | string | — | Line2 continues the street address, when there is more of it. |
address.state | body | string | — | State is the two-letter state or territory code. |
address.zip | body | string | — | ZIP is five or nine digits. |
businessName | body | string | — | BusinessName is line 2: the business or disregarded entity name. |
certification | body | tax.Certification | — | |
certification.by | body | string | — | By is who signed it: the IAM user legal recorded completing the signature. |
certification.document | body | string | — | Document is the /v1/legal document that carries the signature. |
certification.signed | body | integer (int64) | — | Signed is when legal reported the document signed, unix seconds. |
certification.signer | body | string | — | Signer is the IAM user the signature was opened for — the admin who asked. |
certification.status | body | string | — | Status is none, pending (a signature is open) or certified. |
certification.version | body | integer (int64) | — | Version is the profile version the signature covers. |
classification | body | string | — | Classification is line 3a. |
consent | body | tax.Consent | — | |
consent.at | body | integer (int64) | — | At is when the consent was given or withdrawn, unix seconds. |
consent.by | body | string | — | By is the IAM user who gave or withdrew it. |
consent.electronic | body | boolean | — | Electronic is true while the consent stands. |
disclosure | body | string | — | Disclosure is the electronic-delivery disclosure the consent is given against. |
exemptPayee | body | string | — | ExemptPayee is line 4's exempt payee code, 1–13. |
expires | body | integer (int64) | — | Expires is when a certified W-8 stops being valid, unix seconds: the last day of the third calendar year after the year it was signed. |
fatca | body | string | — | FATCA is line 4's FATCA exemption code, A–M. |
foreignOwners | body | boolean | — | ForeignOwners is line 3b: a flow-through entity with foreign partners, owners or beneficiaries. |
foreignTin | body | string | — | ForeignTIN is a W-8's foreign tax identifying number, masked. |
form | body | string | — | Form is w9, w8ben or w8bene. |
name | body | string | — | Name is line 1: the name on the income tax return, or of the foreign individual or organization that is the beneficial owner. |
phone | body | string | — | Phone is the number a 1099 this org files as PAYER prints for it. |
tin | body | string | — | TIN is Part I, masked to its last four digits. |
tinType | body | string | — | TINType is which Part I box: ssn (an SSN or ITIN) or ein. |
updatedAt | body | integer (int64) | — | UpdatedAt is when the profile last changed, unix seconds. |
valid | body | boolean | — | Valid is whether the form establishes what it certifies today — for a W-8, certified for its current version and not expired; for a W-9, a TIN on file. |
version | body | integer (int64) | — | Version counts the W-9's revisions; a certification covers exactly one. |
w8 | body | tax.W8 | — | |
w8.birth | body | string | — | Birth is W-8BEN line 8, the individual's date of birth, YYYY-MM-DD. |
w8.capacity | body | string | — | Capacity is the capacity in which the signer signs for the beneficial owner — "Director", "Authorized officer". |
w8.chapter3 | body | string | — | Chapter3 is W-8BEN-E line 4. |
w8.chapter4 | body | string | — | Chapter4 is W-8BEN-E line 5, the FATCA status. |
w8.country | body | string | — | Country is line 2: the country of citizenship (W-8BEN) or of incorporation or organization (W-8BEN-E), ISO 3166-1 alpha-2. |
w8.giin | body | string | — | GIIN is W-8BEN-E line 9a, when the chapter 4 status carries one. |
w8.noForeignTin | body | boolean | — | NoForeignTIN is W-8BEN line 6b / W-8BEN-E line 9b's alternative: the jurisdiction of residence does not require or issue a foreign TIN. |
w8.treaty | body | tax.Treaty | — | |
w8.treaty.article | body | string | — | Article is the treaty article and paragraph claimed, e.g. "12(2)". |
w8.treaty.conditions | body | string | — | Conditions is the explanation the form asks for: the conditions of the article the beneficial owner meets. |
w8.treaty.country | body | string | — | Country is the treaty country the beneficial owner is resident in. |
w8.treaty.income | body | string | — | Income is the type of income the claim covers: services, rents, royalties or other. |
w8.treaty.lob | body | string | — | LOB is W-8BEN-E line 14b: the treaty's limitation on benefits provision the entity meets. |
w8.treaty.rateBps | body | integer (int64) | — | RateBps is the claimed withholding rate in basis points: 0 is exempt, 1000 is 10%. |
Failure carries the platform error shape — see Errors.
Examples
hanzo has no subcommand for this operation — the CLI serves only what cloud's live route table confirms. Use HTTP or an SDK.
import { Configuration, TaxApi } from 'hanzoai';
const api = new TaxApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.postTaxProfileCertify();from hanzoai.cloud import ApiClient, Configuration
from hanzoai.cloud.api import TaxApi
client = ApiClient(Configuration(access_token=os.environ["HANZO_API_KEY"]))
result = TaxApi(client).post_tax_profile_certify()cfg := hanzoai.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := hanzoai.NewAPIClient(cfg)
resp, _, err := client.TaxAPI.PostTaxProfileCertify(context.Background()).Execute()
if err != nil {
return err
}use hanzo_client::apis::{configuration::Configuration, tax_api};
let mut cfg = Configuration::new();
cfg.bearer_access_token = std::env::var("HANZO_API_KEY").ok();
let result = tax_api::post_tax_profile_certify(&cfg, Default::default()).await?;import ai.hanzo.cloud.ApiClient;
import ai.hanzo.cloud.api.TaxApi;
ApiClient client = new ApiClient();
client.setBearerToken(System.getenv("HANZO_API_KEY"));
var result = new TaxApi(client).postTaxProfileCertify();The method above is the one at the current release of the document. [email protected] (npm) and [email protected] (PyPI) were generated from an earlier release, where this operation carried a different id, so it spells the method differently — regenerating the clients is what makes the two agree. SDKs →
curl -X POST https://api.hanzo.ai/v1/tax/profile/certify \
-H "Authorization: Bearer $HANZO_API_KEY"MCP declares no tool for tax — tools/list on https://api.hanzo.ai/v1/mcp names the products it does reach. Use HTTP or an SDK.
How is this guide?