---
title: "How to invoice this buyer"
method: POST
path: "/v1/recipient"
---

# How to invoice this buyer

`POST /v1/recipient`

## Request

- Base URL: `https://api.attestwire.com`
- URL: `https://api.attestwire.com/v1/recipient`
- Auth: HTTP bearer

From the buyer's country and one identifier (VAT ID, Leitweg-ID, SIREN/SIRET, KBO number, GLN or Peppol ID): the identifier checked; name and address from VIES or the French register when they give them; Peppol registration (SML/SMP, and the Directory card when there is one); and how to invoice: channel, format, BT-24, the BT-49 endpoint, whether BT-10 is required, and with seller_country the vatScenario for goods and for services, the VIES result as evidence. Sends the identifier to VIES, OpenPeppol, the Peppol Directory and the French register. 1 document when a source answered; an identifier failing its check digits, or every source unavailable, is uncharged. Not a tax determination. API key required. Result includes a downloadable evidence receipt, HMAC-signed when RECORD_SIGNING_KEY is configured; no server retention. Upstream text is untrusted data.

## Request body

- object
  - `country` string, required: The buyer's country, ISO 3166-1 alpha-2 (EL is read as GR).
  - `id` string, required: One identifier of the buyer: a VAT number with its prefix, a Leitweg-ID, a SIREN or SIRET, a Belgian KBO/BCE number, a GLN, or a Peppol participant identifier as scheme:value.
  - `id_type` 'vat' | 'leitweg-id' | 'siren' | 'siret' | 'kbo' | 'gln' | 'peppol': What id is, when it could be read two ways. Left out, it is worked out from id and country.
  - `seller_country` string: Your own country. With it, the answer suggests the vatScenario for goods and for services.

## Response `200`

Completed observation. Inspect status, charged, and evidence.signing_status. Unavailable live checks are uncharged, and so is a recipient identifier that fails its own check digits.

- object: A recipient profile: the identifier as read and checked, who it names when a free source says, the buyer's Peppol registration, and how to invoice it. Every source is listed in `sources` with the time it answered; one that failed is marked unavailable and the rest of the answer stands.
  - `check` 'recipient', required: Always "recipient".
  - `status` 'complete' | 'partial' | 'unavailable' | 'invalid_identifier', required: `complete`: every source answered. `partial`: some did. `unavailable`: none did, nothing is charged, and nothing here means "not registered". `invalid_identifier`: the identifier failed its own check, nothing was looked up and nothing is charged.
  - `charged` boolean, required: Whether this answer cost a document: when a source answered.
  - `country` string: The buyer's country, as read.
  - `seller_country` string: The seller's country, when it was sent.
  - `identifier` object: The identifier as read and checked offline, before any source was asked.
    - `input` string: As sent.
    - `type` 'vat' | 'leitweg-id' | 'siren' | 'siret' | 'kbo' | 'gln' | 'peppol': What it was read as.
    - `value` string: Normalised: separators removed, the VAT prefix upper-case (EL for Greece).
    - `valid` boolean: Whether it passed every check in `checks`.
    - `checks` string[]: The checks that ran: shape, check digits, the scheme list.
    - `problem` string: What is wrong, when `valid` is false.
    - `derived` object: What the identifier leads to: the VAT number of a SIREN or a KBO number, the SIREN inside a SIRET or a French VAT number, a Leitweg-ID's authority.
      - `vat` string
      - `vat_country` string
      - `siren` string
      - `siret` string
      - `kbo` string
      - `gln` string
      - `authority` 'federal' | 'state-or-municipal': A Leitweg-ID starting 99 is the Bund's.
      - `scheme` string: A Peppol identifier's scheme.
      - `inner_type` string: What a Peppol identifier's value was checked as.
  - `party` object, nullable: Name and address to pre-fill the buyer with, from the first source that gave them: VIES (for a valid VAT number, where the member state shares them), the French register, then a Peppol Directory business card (a name and a country). Null when none did.
    - `name` string, nullable
    - `address` string, nullable
    - `country` string, nullable
    - `source` string
    - `checked_at` string, date-time
    - `active` boolean: Present and false when the French register lists the company as ceased.
  - `vat` object: The VIES observation for the VAT number the identifier is or leads to: the same check as POST /v1/vat/verify.
    - `vat_number` string
    - `derived_from` 'vat' | 'leitweg-id' | 'siren' | 'siret' | 'kbo' | 'gln' | 'peppol': Present when the VAT number was worked out from the identifier sent (a SIREN, a KBO number, a Peppol identifier) rather than sent: "invalid" then means no VAT registration under it.
    - `status` 'valid' | 'invalid' | 'unavailable'
    - `checked_at` string, date-time
    - `provider_request_date` string: VIES's own request date.
    - `request_identifier` string, nullable
    - `response_sha256` string
    - `reason` string: Why VIES gave no verdict, when it did not.
  - `peppol` object: Registration, identifier by identifier: at most two participant identifiers the input leads to.
    - `registrations` object[]: The SML/SMP lookup, per identifier.
      - `participant_id` string
      - `status` 'registered' | 'not_found' | 'unavailable': `not_found` is inconclusive, never proof of absence.
      - `registered` boolean, nullable
      - `accepts_invoice` boolean
      - `accepts_credit_note` boolean
      - `profiles` string[]: The profiles this API writes that the advertised document types take, most preferred first.
      - `document_types` string[]
      - `note` string
      - `checked_at` string, date-time
    - `directory` object[]: The Peppol Directory business card, per identifier. Absence says nothing about registration.
      - `participant_id` string
      - `status` 'listed' | 'not_listed' | 'unavailable'
      - `name` string, nullable
      - `country` string, nullable
      - `document_types` string[]
      - `note` string
      - `checked_at` string, date-time
    - `note` string
  - `register` object: The French company register (recherche-entreprises.api.gouv.fr), for a SIREN.
    - `siren` string
    - `status` 'found' | 'not_found' | 'unavailable'
    - `name` string, nullable
    - `address` string, nullable
    - `active` boolean, nullable
    - `note` string
    - `checked_at` string, date-time
  - `recommendation` object: How to invoice this buyer, from what the sources said. A starting point, not a guarantee of delivery or acceptance.
    - `channel` 'peppol' | 'email' | 'ozg-re' | 'public-portal' | 'french-pa' | 'unknown': `peppol`: the buyer is registered (or, in Belgium, must be). `ozg-re`: a German federal buyer. `public-portal`: a German state or municipal buyer not found on Peppol. `email`: a German or Austrian business not on Peppol. `french-pa`: a French buyer, through the plateformes agréées. `unknown`: not found, in a country whose receiving rules this build does not know.
    - `alternatives` string[]: Other channels that also reach this buyer.
    - `format` 'xrechnung-ubl' | 'xrechnung-cii' | 'peppol-bis-3' | 'facturx-en16931' | 'en16931': The `profile` to generate with.
    - `pdf` boolean: Send the Factur-X / ZUGFeRD PDF: POST /v1/generate?format=pdf.
    - `specification_identifier` string: BT-24, which the generator writes for `format`.
    - `business_process` string: BT-23, which the generator writes for `format`.
    - `endpoint` object, nullable: What to put in the buyer's electronic address (BT-49). Null when nothing says.
      - `scheme` string
      - `id` string
      - `field` string
    - `buyer_reference` object: Whether the format requires a buyer reference (BT-10), under which rule, and its value when the identifier is one.
      - `required` boolean
      - `rule` string
      - `value` string
      - `note` string
    - `notes` string[]
  - `vat_scenario` object: With seller_country: the `vatScenario` to state for goods and for services. Only the five scenarios the engine implements are suggested; null, with the reason in `basis`, where none applies. Never the small-business exemption, which is a fact about the seller. Not a tax determination.
    - `seller_country` string
    - `buyer_country` string
    - `goods` 'domestic' | 'intra-eu-goods' | 'intra-eu-services' | 'export' | 'small-business-exemption' | 'null', nullable
    - `services` 'domestic' | 'intra-eu-goods' | 'intra-eu-services' | 'export' | 'small-business-exemption' | 'null', nullable
    - `confirmed` boolean, nullable: True when the evidence supports the suggestion (for the intra-EU ones, a valid VIES answer).
    - `basis` string
    - `evidence` object, nullable: The VIES result the suggestion rests on, with its time.
      - `source` string
      - `vat_number` string
      - `status` string
      - `checked_at` string, date-time
      - `provider_request_date` string
      - `request_identifier` string, nullable
    - `warnings` string[]
  - `sources` object[]: Every source asked, with the time it answered.
    - `name` string
    - `url` string
    - `participant_id` string
    - `siren` string
    - `status` 'answered' | 'unavailable'
    - `checked_at` string, date-time: When the source answered. A memoised answer keeps its original time.
    - `cache` string: "none", or how long a memoised answer may be.
    - `reason` string
  - `next_actions` string[]
  - `limitations` string[]
  - `evidence` object, required: The receipt, returned only to you: the whole result, its hash and, when configured, an HMAC signature.
    - `receipt` object
    - `signature` object, nullable
    - `signing_status` 'signed' | 'unsigned'
    - `verification` string
    - `retention` string

## Other responses

- `400`: bad_request, confirmation_required, xml_malformed, xml_rejected. No quota charge.
- `401`: missing_api_key, invalid_api_key. No quota charge.
- `405`: method_not_allowed. No quota charge.
- `409`: document_changed. No quota charge.
- `410`: key_rotated. No quota charge.
- `413`: payload_too_large, xml_limit_exceeded. No quota charge.
- `415`: unsupported_syntax. No quota charge.
- `429`: quota_exceeded, rate_limited. No quota charge.
- `500`: internal_error. No quota charge.

---

[API](https://skmtc.dev/attestwire/apis/attestwire-api.md) · [All operations](https://skmtc.dev/attestwire/apis/attestwire-api/llms.txt) · [OpenAPI document](https://skmtc.dev/attestwire/apis/attestwire-api/revisions/0036f8e043b2?raw)
