Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/jithox-com:jithox-com-vat-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Jithox REST — invoice checks for a backend Vat API
version: 1.2.0
summary: EU VAT numbers (VIES), Peppol receivers and IBANs, checked from a backend with a connection credential a person creates.
description: 'A person creates a Jithox connection at https://jithox.com/mcp/account#connection and gives its secret (jxc_live_…) to the backend, which sends it as a Bearer token on every route except POST /api/invoice/review. POST /api/v1/vat/verify checks EU VAT numbers against VIES. Price: 1 credits (EUR 0.01) per row VIES answered (valid or invalid), charged once per delivery from the workspace''s prepaid credits; credits are added at https://jithox.com/plan. New workspaces get 100 free VAT checks against the EU VIES register, once per workspace, no card. They pay for VAT checks on the REST API and on the Jithox MCP at https://jithox.com/api/mcp, not for the E-Invoice server''s tools. Granted when the workspace creates a connection and has had no trial before, within a limit per network and per day. Bought credits are spent first. A company lookup by VAT number on the Jithox MCP uses 2 of the 100. Without a trial, or once it is used up, the normal 402 applies. A row VIES did not answer (unavailable), a malformed or duplicate number, or a number VIES does not cover costs nothing. The answer carries the ledger booking id (billing.receiptRunId), which is not a signed receipt; no signed or hash-bound receipt is returned. With the optional requesterVatId (your own EU VAT number), a valid row also carries the European Commission''s consultation number for that lookup — the Commission''s record that it took place, not a receipt from Jithox. Not legal or tax advice: VIES states whether a number is registered for intra-EU trade at the moment it answered. The other routes are the MCP tools of the same name over plain HTTP, with the same answer: POST /api/v1/peppol/participant (lookup_peppol_participant, free); POST /api/v1/iban/verify (verify_iban, free); POST /api/v1/payment/preflight (preflight_payment, free). POST /api/invoice/review checks one invoice before it is sent or paid; it is free and needs no credential. No route returns a signed or hash-bound payment receipt. With a signing key configured, POST /api/v1/payment/preflight also return `evidence`: a signed statement of the verdict and the checks (Ed25519 compact JWS), verifiable offline against https://jithox.com/.well-known/jwks.json or at https://jithox.com/api/v1/evidence/verify. It proves what Jithox decided, not that the decision is right.'
contact:
url: https://jithox.com/rest-api
servers:
- url: https://jithox.com
tags:
- name: Vat
paths:
/api/v1/vat/verify:
post:
operationId: verifyVat
summary: Check up to 20 EU VAT numbers against VIES
description: Send up to 20 rows; the answer has one row per input row, in order. Branch on rows[].verdict. The whole call is bounded at 40000 ms; rows VIES did not answer in time come back unavailable and are listed in result.retry.indexes. Re-sending the same rows with the same x-jithox-idempotency-key is charged once.
security:
- jithoxConnection: []
parameters:
- name: x-jithox-idempotency-key
in: header
required: false
description: 'Optional. 8–100 characters of A–Z a–z 0–9 . _ : -. The same key with the same rows is charged once.'
schema:
type: string
pattern: ^[A-Za-z0-9._:-]{8,100}$
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/VerifyRequest'
example:
rows:
- reference: C-001
vatId: BE0403170701
requesterVatId: BE0403170701
responses:
'200':
description: The check ran. Branch per row on `verdict`. `billing` says what was charged.
content:
application/json:
schema:
$ref: '#/components/schemas/VerifyResponse'
'400':
description: The request could not be read (not JSON, no rows, a reference too long, a malformed idempotency key, a requesterVatId VIES would refuse). Nothing ran; nothing was charged.
content:
application/json:
schema:
$ref: '#/components/schemas/ListRefusal'
'401':
description: No credential, or not an active connection (unknown, revoked, expired). Nothing ran; nothing was charged.
content:
application/json:
schema:
$ref: '#/components/schemas/Unauthorized'
headers:
WWW-Authenticate:
schema:
type: string
description: Bearer realm="jithox-connection"
'402':
description: The workspace's credits cannot cover the most these rows can cost. VIES was not asked; nothing was charged.
content:
application/json:
schema:
$ref: '#/components/schemas/InsufficientCredits'
'403':
description: These rows can cost more than the per-call bound the person set on this connection. Nothing ran; nothing was charged.
content:
application/json:
schema:
$ref: '#/components/schemas/BudgetExceeded'
'413':
description: More than 20 rows, or a body over 65536 bytes. Nothing ran; nothing was charged.
content:
application/json:
schema:
$ref: '#/components/schemas/ListRefusal'
'429':
description: Too many requests for this workspace. Nothing ran; nothing was charged.
headers:
Retry-After:
description: Seconds to wait before retrying.
schema:
type: integer
content:
application/json:
schema:
$ref: '#/components/schemas/RateLimited'
'503':
description: The connection store is not answering, so the credential cannot be checked. Nothing ran; nothing was charged.
headers:
Retry-After:
description: Seconds to wait before retrying.
schema:
type: integer
content:
application/json:
schema:
$ref: '#/components/schemas/StoreUnavailable'
x-jithox-pricing:
tool: check_vat_list
unit: answered_row
pricePerUnitCredits: 1
pricePerUnitEur: EUR 0.01
maxCreditsPerCall: 20
source: TOOL_PRICE_CREDITS.check_vat_list — the same price the check_vat_list MCP tool and the website charge.
tags:
- Vat
components:
schemas:
Billing:
type: object
properties:
charged:
type: boolean
description: Whether this request moved credits.
credits:
type: integer
minimum: 0
description: Credits this delivery cost (1 credit = EUR 0.01).
units:
type: integer
minimum: 0
description: Rows VIES answered — what `credits` was computed from.
pricePerUnitCredits:
type: integer
minimum: 0
reason:
type: string
receiptRunId:
type: string
description: 'The id of the credit-ledger booking for this delivery. A reference, not a signed receipt: this route returns no signed or hash-bound receipt, and /plan lists the booking without this id.'
balanceAfter:
type: integer
description: The workspace's credit balance after this charge (the trial credit left, when funding is trial_credit).
funding:
enum:
- trial_credit
description: 'Present only when the workspace''s one-time free trial credit paid for this delivery. Absent: the prepaid credits paid.'
required:
- charged
- credits
- units
- pricePerUnitCredits
- reason
additionalProperties: false
VatRow:
type: object
properties:
index:
type: integer
minimum: 0
description: Position in the request, from 0. Output row i is input row i.
reference:
type:
- string
- 'null'
description: Your own label for the row, echoed.
input:
type: string
description: The number as sent.
normalized:
type:
- string
- 'null'
description: Upper case, separators removed; Greek numbers under VIES's prefix EL.
countryCode:
type:
- string
- 'null'
description: ISO 3166-1 alpha-2 of the issuing member state.
local:
enum:
- well_formed
- empty
- malformed
- not_covered
- duplicate
description: What the free local check found.
duplicateOf:
type: integer
minimum: 0
description: 'For a duplicate: the index of the earlier row that carries the answer.'
register:
enum:
- valid
- invalid
- unknown
- not_run
description: What the EU register (VIES) said. `unknown` = no answer; never folded into `invalid`.
verdict:
enum:
- valid
- invalid
- unavailable
- not_checked
description: 'The one word to branch on. valid / invalid: VIES answered (charged). unavailable: VIES was asked and gave no answer — outage, rate limit, time ran out; free; the row is in result.retry.indexes. not_checked: VIES was not asked for this row (malformed, empty, not covered, duplicate); free.'
registeredName:
type: string
description: 'The name VIES returned. Often absent: several member states never share it.'
unknownReason:
enum:
- rate_limited
- no_answer
- not_reached
- not_authorised
- requester_rejected
description: 'Why `unknown`. requester_rejected: the European Commission refused the requesterVatId sent with this call — a refusal about who asked, not about this number; send the row again without requesterVatId.'
detail:
type: string
description: One sentence a bookkeeper can act on.
checkedAt:
type: string
format: date-time
description: When VIES answered. Only on valid and invalid.
consultationNumber:
type: string
description: The European Commission's own consultation number (requestIdentifier) for this lookup. Only on a `valid` row, and only when a requester reached VIES (requesterVatId on this call). It is the Commission's record that this consultation took place at that moment, on the requester's name — not a signed Jithox receipt, and nothing more about the company.
consultationRequester:
type: string
description: The requester VAT number the Commission recorded this consultation against. Only alongside consultationNumber.
consultationAt:
type: string
format: date-time
description: The Commission's own requestDate for the consultation, never our clock. Only alongside consultationNumber, and only when VIES gave one.
required:
- index
- reference
- input
- normalized
- countryCode
- local
- register
- verdict
- detail
additionalProperties: false
BudgetExceeded:
type: object
properties:
ok:
const: false
error:
type: object
properties:
code:
const: budget_exceeded
reason:
const: per_call_budget_exceeded
message:
type: string
requiredMinorUnits:
type: integer
minimum: 0
description: The most these rows can cost, in euro cents.
maxMinorUnitsPerCall:
type: integer
minimum: 0
description: The bound the person set on this connection.
currency:
const: EUR
manageAt:
const: https://jithox.com/mcp/account#connection
required:
- code
- reason
- message
- requiredMinorUnits
- maxMinorUnitsPerCall
- currency
- manageAt
additionalProperties: false
required:
- ok
- error
additionalProperties: false
Pricing:
type: object
properties:
localChecks:
const: included
registerCheck:
type: string
unit:
const: answered_row
pricePerUnitCredits:
type: integer
minimum: 0
pricePerUnitEur:
type: string
maxCreditsPerCall:
type: integer
minimum: 0
chargedWhen:
type: string
neverCharged:
type: string
required:
- localChecks
- registerCheck
- unit
- pricePerUnitCredits
- pricePerUnitEur
- maxCreditsPerCall
- chargedWhen
- neverCharged
additionalProperties: false
ListRefusal:
type: object
properties:
ok:
const: false
schema_version:
const: jx.vat-list-check/v1
error:
type: object
properties:
code:
enum:
- bad_request
- no_rows
- too_many_rows
- reference_too_long
- request_too_large
- invalid_idempotency_key
- requester_invalid
message:
type: string
limit:
type: object
properties:
name:
type: string
max:
type: integer
minimum: 0
actual:
type:
- integer
- 'null'
required:
- name
- max
- actual
additionalProperties: false
issues:
type: array
items:
type: string
description: 'For requester_invalid: what is wrong with requesterVatId.'
required:
- code
- message
additionalProperties: false
limits:
$ref: '#/components/schemas/Limits'
required:
- ok
- schema_version
- error
additionalProperties: false
Consultation:
type: object
description: Said once per answer, so an absent consultationNumber is never left to be guessed at. The number is the Commission's record of the lookup, not a signed receipt.
properties:
available:
type: boolean
description: Whether a `valid` row CAN carry a consultationNumber on this call.
reason:
enum:
- not_requested
- requester_rejected
- malformed
- not_a_requester_state
description: 'Why not, when not; absent when available. not_requested: no requesterVatId was sent (and none is configured). requester_rejected: the European Commission refused the requesterVatId sent with this call. malformed / not_a_requester_state: the deployment''s configured fallback requester cannot be sent.'
note:
type: string
description: One sentence saying exactly what the consultation number is and is not.
required:
- available
- note
additionalProperties: false
VatTotals:
type: object
properties:
rows:
type: integer
minimum: 0
wellFormed:
type: integer
minimum: 0
empty:
type: integer
minimum: 0
malformed:
type: integer
minimum: 0
notCovered:
type: integer
minimum: 0
duplicate:
type: integer
minimum: 0
valid:
type: integer
minimum: 0
invalid:
type: integer
minimum: 0
unknown:
type: integer
minimum: 0
notRun:
type: integer
minimum: 0
required:
- rows
- wellFormed
- empty
- malformed
- notCovered
- duplicate
- valid
- invalid
- unknown
- notRun
additionalProperties: false
VerifyRequest:
type: object
properties:
rows:
type: array
minItems: 1
maxItems: 20
items:
type: object
properties:
reference:
type:
- string
- 'null'
maxLength: 80
description: Your own label, echoed back.
vatId:
type: string
description: The VAT number as written, with its country prefix. Spaces, dots and dashes are fine.
required:
- vatId
additionalProperties: false
requesterVatId:
type: string
maxLength: 20
description: Optional. YOUR OWN EU VAT number, with its country prefix (Greece as EL; XI cannot be a requester). A `valid` row then carries the European Commission's consultationNumber for that lookup, registered to you. Not a signed receipt. A value VIES would refuse is a 400 before anything runs or is charged; rows VIES refuses for this requester come back unknown (requester_rejected), never invalid, and cost nothing. Used for this call only, stored nowhere.
required:
- rows
additionalProperties: false
StoreUnavailable:
type: object
properties:
ok:
const: false
error:
type: object
properties:
code:
const: connection_store_unavailable
message:
type: string
required:
- code
- message
additionalProperties: false
required:
- ok
- error
additionalProperties: false
InsufficientCredits:
type: object
properties:
ok:
const: false
error:
type: object
properties:
code:
const: insufficient_credits
message:
type: string
requiredCredits:
type: integer
minimum: 0
description: 'The most these rows can cost: price × well-formed rows.'
pricePerAnsweredRowCredits:
type: integer
minimum: 0
topUpUrl:
const: https://jithox.com/plan
description: Where a person adds credits to this workspace.
required:
- code
- message
- requiredCredits
- pricePerAnsweredRowCredits
- topUpUrl
additionalProperties: false
required:
- ok
- error
additionalProperties: false
VerifyResponse:
type: object
properties:
ok:
const: true
result:
type: object
properties:
ok:
const: true
schema_version:
const: jx.vat-list-check/v1
registerTier:
type: boolean
description: Whether VIES was asked for this request. False when no row was well-formed.
rows:
type: array
items:
$ref: '#/components/schemas/VatRow'
totals:
$ref: '#/components/schemas/VatTotals'
answeredRows:
type: integer
minimum: 0
description: 'valid + invalid: the rows VIES answered. This is what is billed.'
retry:
type: object
description: The rows worth sending again (VIES gave no answer).
properties:
indexes:
type: array
items:
type: integer
minimum: 0
advice:
type: string
required:
- indexes
- advice
additionalProperties: false
required:
- ok
- schema_version
- registerTier
- rows
- totals
- answeredRows
- retry
additionalProperties: false
source:
type: object
properties:
register:
const: EU VIES
required:
- register
additionalProperties: false
consultation:
$ref: '#/components/schemas/Consultation'
billing:
$ref: '#/components/schemas/Billing'
pricing:
$ref: '#/components/schemas/Pricing'
limits:
$ref: '#/components/schemas/Limits'
required:
- ok
- result
- source
- consultation
- billing
- pricing
- limits
additionalProperties: false
Unauthorized:
type: object
properties:
ok:
const: false
error:
type: object
properties:
code:
const: unauthorized
reason:
enum:
- missing_credential
- invalid_credential
message:
type: string
required:
- code
- reason
- message
additionalProperties: false
authorization:
type: object
properties:
scheme:
const: Bearer
credentialPrefix:
const: jxc_live_
createAt:
const: https://jithox.com/mcp/account#connection
description: Where a person creates (and revokes) the credential.
howToCreate:
type: string
required:
- scheme
- credentialPrefix
- createAt
- howToCreate
additionalProperties: false
required:
- ok
- error
- authorization
additionalProperties: false
RateLimited:
type: object
description: The shared rate limiter's answer. See the Retry-After header.
properties:
error:
const: rate_limited
retryAfterSeconds:
type: integer
minimum: 0
required:
- error
- retryAfterSeconds
additionalProperties: false
Limits:
type: object
description: The limits every answer repeats.
properties:
maxRowsPerCall:
type: integer
minimum: 0
maxReferenceChars:
type: integer
minimum: 0
maxVatIdChars:
type: integer
minimum: 0
deadlineMs:
type: integer
minimum: 0
required:
- maxRowsPerCall
- maxReferenceChars
- maxVatIdChars
- deadlineMs
additionalProperties: false
securitySchemes:
jithoxConnection:
type: http
scheme: bearer
description: A Jithox connection secret (jxc_live_…). A person signs in at https://jithox.com/mcp/account#connection, creates a connection and copies the secret (shown once); the same page revokes it. It bills that person's workspace.