Skip to main content
Glama

Create invoice from data

well_create_invoice_from_data

Create an invoice in Well from data you extracted by reading an invoice (your own OCR) — you send the structured fields, not the file.

Well persists the invoice + its line items + payment means using the same pipeline as uploaded documents. Fill every field you can read from the document:

  • issuer / receiver: { name (required), company_id?, domain?, tax_id? }

  • reference_number, issue_date (YYYY-MM-DD), due_date? (YYYY-MM-DD), currency (ISO 4217)

  • totals?: { items_total?, tax_total?, grand_total }

  • line_items[]: { name, quantity?, unit_price, currency?, tax_rate? }

  • payment_means?[]: { type, iban?, bic?, scheme? }

  • status?: draft | issued | paid | canceled

ONE CALL IS THE WHOLE WRITE. This tool takes the invoice's status and both parties' company ids, so a create never needs a well_update_invoice after it:

  • The user asked to DRAFT an invoice → pass status: "draft" here.

  • You already found the company (well_query_records, well_get_entity) → pass its company_id on that party. Naming the party without its id re-resolves it, which can attach the invoice to the wrong company or create a duplicate one.

Creating and then patching the same invoice writes twice and shows the user two confirmations for one action. Put the intent in this call.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
issuerYes
statusNoThe invoice's lifecycle status. Set it here when the user asked for one ("draft an invoice") — do NOT create and then call well_update_invoice to change it. Omitted, the status is derived from the document type.
totalsNo
currencyYesISO 4217 (3 letters).
due_dateNoISO 8601 YYYY-MM-DD.
receiverYes
issue_dateYesISO 8601 YYYY-MM-DD.
line_itemsYes
workspace_idNoTarget workspace. Omit when the token authorizes one workspace. Required when it authorizes several — a write lands in exactly one workspace and this call would not say which.
payment_meansNo
conversation_idNoThe conversation id returned by the previous Well result, in its meta under well/conversation_id, in its structuredContent, or in its JSON text block. Pass it back on every call in the same conversation, including a call a card makes, so the chosen workspace and the earlier answers still apply. It decides the conversation on its own: nothing the host states about the session replaces it. Omit it only on the first call of a conversation.
idempotency_keyNoOptional client-supplied key. A retried write with the same key returns the original result instead of re-applying the operation.
reference_numberYes

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
errorNo
successYes
invoice_idNo
document_idNo
payment_meansNo
conversation_idNoThe conversation this result belongs to. Pass it back as the conversation_id argument on every later Well call in the same conversation.
reference_numberNo
invoice_item_countNo
conversation_id_noteNoPresent only when the server opened a fresh lane, stating that no choice recorded earlier was read.
conversation_id_sourceNoWhere the conversation id came from: the host's own request meta, the caller's argument, or a fresh lane the server opened.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed4 schema fields changed
    • addedInput schema / properties / conversation_id
      Added value: +{
      +  "description": "The conversation id returned by the previous Well result, in its meta under well/conversation_id, in its structuredContent, or in its JSON text block. Pass it back on every call in the same conversation, including a call a card makes, so the chosen workspace and the earlier answers still apply. It decides the conversation on its own: nothing the host states about the session replaces it. Omit it only on the first call of a conversation.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / conversation_id
      Added value: +{
      +  "description": "The conversation this result belongs to. Pass it back as the conversation_id argument on every later Well call in the same conversation.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / conversation_id_note
      Added value: +{
      +  "description": "Present only when the server opened a fresh lane, stating that no choice recorded earlier was read.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / conversation_id_source
      Added value: +{
      +  "description": "Where the conversation id came from: the host's own request meta, the caller's argument, or a fresh lane the server opened.",
      +  "enum": [
      +    "host_meta",
      +    "argument",
      +    "minted"
      +  ],
      +  "type": "string"
      +}
  2. Changed4 schema fields changed
    • addedInput schema / properties / issuer / properties / name / maxLength
      Added value: +255
    • addedInput schema / properties / line_items / items / properties / name / maxLength
      Added value: +255
    • addedInput schema / properties / receiver / properties / name / maxLength
      Added value: +255
    • addedInput schema / properties / reference_number / maxLength
      Added value: +100
  3. Changed1 schema field changed
    • changedInput schema / properties / workspace_id / description
      Previous value: -"Target workspace. Omit to use the only authorized workspace, or (for read tools) to query all authorized workspaces grouped by workspace. Required for write tools when the token authorizes more than one workspace."New value: +"Target workspace. Omit when the token authorizes one workspace. Required when it authorizes several — a write lands in exactly one workspace and this call would not say which."
  4. Changed3 schema fields changed
    • addedInput schema / properties / issuer / properties / company_id
      Added value: +{
      +  "description": "An existing company in the workspace, bound directly — ALWAYS send this when you already know the company (e.g. you found it with well_query_records). Without it the party is re-resolved from name/domain/tax_id, which can attach the invoice to a different company or mint a duplicate.",
      +  "format": "uuid",
      +  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
      +  "type": "string"
      +}
    • addedInput schema / properties / receiver / properties / company_id
      Added value: +{
      +  "description": "An existing company in the workspace, bound directly — ALWAYS send this when you already know the company (e.g. you found it with well_query_records). Without it the party is re-resolved from name/domain/tax_id, which can attach the invoice to a different company or mint a duplicate.",
      +  "format": "uuid",
      +  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
      +  "type": "string"
      +}
    • addedInput schema / properties / status
      Added value: +{
      +  "description": "The invoice's lifecycle status. Set it here when the user asked for one (\"draft an invoice\") — do NOT create and then call well_update_invoice to change it. Omitted, the status is derived from the document type.",
      +  "enum": [
      +    "draft",
      +    "issued",
      +    "paid",
      +    "canceled"
      +  ],
      +  "type": "string"
      +}
  5. First observed

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate destructiveHint=false and readOnlyHint=false, so the description doesn't need to repeat those. It adds important behavioral details: that one call is the whole write, that re-resolving without company_id can attach to wrong company or create duplicates, and that patching after create causes two confirmations. It does not mention idempotency_key but that is in the schema. Slight deduction for not mentioning the persistence pipeline in detail, but it's clear enough.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections and bullet points, but it is quite long. It front-loads the core purpose and then provides detailed usage guidance. While lengthy, every sentence adds value, and the structure helps readability. Minor deduction for length, but it's justified by the complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the tool's purpose, usage, key parameters, and integration with sibling tools. It explains edge cases like re-resolution and workspace selection. The output schema exists, so return values need not be described. For a complex write tool, this is remarkably complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 54%, and the description compensates by explaining key parameters like company_id (always send when known), status (set it here not via update), and workspace_id (omit when single workspace). It also explains line_items, totals, and payment_means structure. However, some parameters like reference_number, issue_date, and currency are only described in schema, but the description covers the important ones.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool creates an invoice from structured data extracted via OCR, not from a file. It lists the fields to be filled and explicitly differentiates from sibling tools like well_create_invoice_document (which likely handles file uploads) and well_update_invoice (which is for patching).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says to use this tool for the whole write operation, when to pass a status (when user asked for draft), when to pass company_id (when already found), and warns against creating and then patching. It also tells when to omit workspace_id based on token authorization. This is exemplary guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources