Use Emboss from agent frameworks (A2A)
Emboss also speaks A2A (Agent2Agent), a protocol for one agent to discover and delegate tasks to another. A2A is complementary to MCP: MCP connects Emboss to a chat client or IDE, and A2A lets an agent orchestrator, such as Google's ADK, LangGraph, or an enterprise agent stack, discover Emboss by semantic search and delegate a form-filling task to it directly. See the MCP tools reference for the MCP connection.
Connect
Emboss publishes a signed agent card at
https://api.getemboss.ai/.well-known/agent-card.json. A compliant A2A
client reads the card to learn the server's URL, its skills, and how to
authenticate, then sends it tasks at https://api.getemboss.ai/a2a.
Here's a Python client using the a2a-sdk
that resolves the card from Emboss's base URL and completes a fill_form
task. The SDK's message types are protobuf, so structured arguments go
through json_format.ParseDict:
import asyncio, uuid, httpx
from google.protobuf import json_format
from a2a.client import create_client, ClientConfig
from a2a.types import Message, Part, Role, SendMessageRequest
API_KEY = "sk_..."
async def main():
async with httpx.AsyncClient(
headers={"Authorization": f"Bearer {API_KEY}"}
) as http:
client = await create_client(
"https://api.getemboss.ai",
client_config=ClientConfig(httpx_client=http),
)
message = Message(message_id=str(uuid.uuid4()), role=Role.ROLE_USER)
message.parts.append(Part(data=json_format.ParseDict(
{"form_id": "your-form-id", "values": {"Full name": "Jordan Lee"}},
Part().data,
)))
json_format.ParseDict({"skillId": "fill_form"}, message.metadata)
request = SendMessageRequest(message=message)
async for update in client.send_message(request):
print(update)
asyncio.run(main())
Auth
Emboss's card declares two security schemes: an HTTP Bearer scheme using an
Emboss API key (see Authentication), and OAuth 2.1
for clients that support it. Either way, the connection is scoped to the same
owner as the rest of the Emboss API: a task can only read and write the forms
that key or token already has access to. Callers with no Emboss account can
pay per job instead; see Pay per job with x402.
A request whose Authorization: Bearer token matches no account (a mistyped,
revoked or turned-off key, or an expired sign-in) is refused with 401; it
never falls back to paying per job. Leave the header out to pay per job.
send_fax is also available that way: an anonymous caller pays per
transmitted page and the task stays working until delivery.
Free skills need no payment, only tokens: an anonymous caller sends the artifact_token for each source instead of paying.
The key that signs the agent card also signs every entry in Emboss's discovery catalogue, and the same public key is published as a DID document. Trust and verification describes the framework and how to check a signature yourself.
Plain-language requests
Signed-in callers (an API key or an OAuth sign-in) can describe the job in words instead of
naming a skill: leave metadata.skillId out and send a text part, with any files as file parts.
Emboss works out which skill you mean and runs it with the same billing and permissions as
naming it yourself.
- When the request is unclear, could mean two different paid jobs, or is missing something, the
task pauses in
input-requiredwith a question. Answer it with a message on the same task. Emboss asks at most three questions, and a request that gets no answer for 24 hours ends as failed. - While a question waits, Emboss keeps the request's words and any attached files for up to 24 hours, then deletes them. They are deleted as soon as the task ends, and a waiting task can be canceled.
- Before sending a fax, Emboss names the document and the full number it will fax to, and waits for a yes.
- A request that is not about PDF forms is declined with a list of what Emboss can do.
- Every plain-language task ends with one readable sentence alongside the usual result. When the job is a page tool (compose, merge, extract, delete, reorder or rotate pages), the sentence carries a download link anyone holding it can open, with no API key, for about an hour, as long as Emboss keeps that file.
- Each message Emboss reads, a request or your answer to its question, counts once toward the same per-account rate limit as a request that names a paid skill (see Rate limit). The job it runs does not count again, and a yes to a fax is not counted.
A caller can also ask whether a fax went through, for example "did my fax go through?". Emboss answers from the most recent fax sent in that conversation, or else the caller's most recent fax from the last 7 days, sent from any of Emboss's surfaces, with the masked number and whether it was delivered, is still sending, or did not go through. Checking is free.
Requests that name a skill work exactly as before. Callers without an account, who pay per job with x402, still name a skill.
To add Emboss to Gemini Enterprise, see Use Emboss in Gemini Enterprise.
Several jobs in one request
A plain-language request can ask for up to five jobs in a row, such as "fill the W-9 from these
notes and fax it to 555 201 0142." Emboss answers with the jobs it will run, one numbered line
each, and an estimated total, and waits in input-required. Reply yes to start; any other reply
plans again. Nothing runs before you reply yes, even when every job is free. A request that reads
as several jobs but can only plan as one is confirmed the same way, so you see what is not
included before anything runs.
- The estimated total uses the same prices as your bill and counts your free jobs first. It says "about" when a price depends on a document Emboss has not read yet.
- Billing does not change: each job is billed as it runs, exactly as if you had asked for it on its own. If a job fails, the run stops there: the jobs before it stay done and billed, and the jobs after it do not run.
- The task shows which job is running. A reading or checking job, such as a read back, a check of a filled form, or a look at a form's fields, sends its result as the run goes, not only at the end; a check's summary names the missing or problem fields. The task ends with one sentence per job and the download links. When the last job is a fax, the task completes when the fax is delivered.
- At most five jobs, run in the order you asked for them. A fax can only be the last job, and replying yes to the plan is also your yes to send that fax; no second fax question follows. A job Emboss cannot run as asked, such as a review in the middle of a chain, faxing every copy of a batch, or a fax before another job, is explained or asked about, never skipped or changed.
- A plan is refused up front when it could not finish: a connection without write access for a job that writes, or an account without a card for a fax or past its free allowance.
- Like any plain-language message, the request counts once toward the rate limit; your yes and the jobs it runs do not count again.
- The request's words and any attached files are kept until the last job has run, then deleted; up to 24 hours while a question or the plan waits for your answer.
- A later job can use what an earlier one made: a form made fillable can be filled; a filled form or a new PDF can be faxed, merged, split or read back; values read back can fill a new form.
Skills
Every task names a skillId in the message metadata; a task without one, or
with an id Emboss doesn't recognize, is rejected. There is no intent
inference: the client picks the skill.
| Skill | What it does | Input | Output |
|---|---|---|---|
make_fillable | Detects fields on a flat PDF and makes it fillable. | A FilePart PDF. | A form_id and the detected field inventory. |
fill_form | Fills a ready form with values. | A form reference (form_id or a PDF FilePart) and a values DataPart. | The form_id, a download_url, the unmatched values, and the filled PDF's artifact_id. |
fill_from_context | Fills a form using answers pulled from context documents or notes. | A form reference (a form_id, a PDF FilePart, or a library slug) plus one or more context FileParts and/or context_text/context_urls. | The filled PDF as a FilePart, plus the form_id, the filled and dropped counts, any warnings, and the artifact_id. |
prepare | Prepares a form instead of filling it: nothing is written into the PDF until a later commit. | A form reference (a form_id, a PDF FilePart, or a library slug) plus context FileParts and/or text, and an optional policy (safe or strict). | A proposal_id and the proposal: every field's proposed answer with the document it came from, the questions still open, the values awaiting confirmation, and the signatures and attachments a person still has to supply. |
commit | Commits a proposal from prepare: writes the remaining values, renders the PDF with text that fits, checks it, and returns a receipt. | A proposal_id DataPart, plus an optional confirm list of field ids, any values still needed (field_id, value, and an optional note), an optional policy, and an optional package. | The verification result, a receipt link, the filled PDF, and the submission package when one was asked for. |
verify | Checks a filled PDF against a form's contract: required fields, allowed options, consistent choices, text that fits, empty signature boxes. | A form_id and the filled PDF (a FilePart or pdf_url). | complete, review required or incomplete, plus the list of issues found. |
fill_batch | Fills the form once per row of a spreadsheet. | A form_id (required) plus a CSV FilePart or csv_text, and an optional mapping. | Per-row results and a zip_url once the batch finishes. A batch over 50 rows keeps running after the answer: check the task with tasks/get for the finished zip. |
suggest_mapping | Proposes which spreadsheet column fills which form field. | A form_id (required) plus a CSV FilePart, csv_text, or a columns DataPart. | A mapping of column to field id. |
find_forms | Searches the forms already in the library. | A query, state, and limit DataPart. | Matching forms, each with its id, title, state, pages and field_count. |
find_form | Finds a blank US federal form in the Emboss library, by name, number or alias. | A query DataPart, such as W-9, i9 or taxpayer identification. | Each matching form's slug, title, agency, revision and page_count; pass a slug as library on make_fillable, fill_from_context or prepare to start from that form. |
get_form | Reads one form's status and field inventory. | A form_id DataPart. | The form's status and, once ready, its fields. |
read_form | Reads a filled PDF's values back out, labelled, without storing the file. | The filled PDF (a FilePart or pdf_url) and an optional form_id DataPart. | recognised, fields, unmatched, counts, and complete. |
send_fax | Sends a PDF to a fax number and tracks delivery. The task stays working until the fax is delivered or fails; poll tasks/get. Signed-in callers need a payment method on file; without one the task fails before anything is sent. | A to DataPart (E.164) with a job_id, form_id, or artifact_id, or a sources list (each entry an artifact_id, an artifact_token for anonymous callers, and optional pages), or one or more PDF FileParts. Anonymous x402 callers send FileParts or an artifact_id with its artifact_token. | A receipt: job_id, status, pages, price_cents, destination_masked, artifact_id, and source_artifact_ids. |
attach | Attaches a supporting document to a proposal before commit. | A proposal_id DataPart, a file part, and an optional for in the data part naming a required attachment. | The attachment's n, filename, bytes, and sha256. |
quote_job | Prices a job before any paid work runs. | The target skill (make_fillable, fill_form, fill_from_context, suggest_mapping, fill_batch, or send_fax) and that skill's own input, exactly as a direct call would take. | A quote_id, the price and its expiry. With no account the price is fixed; for an account the job is billed like a direct call, so the free allowance and the documents' measured size apply. |
execute_quote | Runs the job priced by an earlier quote_job, from its staged inputs, with no re-upload. | A quote_id DataPart. | The same result the quoted skill's direct call returns: a filled PDF, a fillable form, or a batch of filled copies. |
compose_pdf | Free. Builds one PDF from several artifacts, each with an optional page selection and rotation. | A sources DataPart: a list of {artifact_id, pages, rotate}, plus an artifact_token per entry for anonymous callers. | The new artifact_id and, for anonymous callers, its artifact_token. |
merge_pdf | Free. Joins whole PDFs in order. | A sources DataPart: a list of {artifact_id}, plus an artifact_token per entry for anonymous callers. | The new artifact_id and, for anonymous callers, its artifact_token. |
extract_pages | Free. Keeps only the named pages of one artifact. | An artifact_id, pages, and an artifact_token for anonymous callers. | The new artifact_id and, for anonymous callers, its artifact_token. |
delete_pages | Free. Removes the named pages of one artifact. | An artifact_id, pages, and an artifact_token for anonymous callers. | The new artifact_id and, for anonymous callers, its artifact_token. |
reorder_pages | Free. Puts one artifact's pages in a new order. | An artifact_id, order, and an artifact_token for anonymous callers. | The new artifact_id and, for anonymous callers, its artifact_token. |
rotate_pages | Free. Rotates named pages of one artifact. | An artifact_id, rotations (a list of {pages, degrees}), and an artifact_token for anonymous callers. | The new artifact_id and, for anonymous callers, its artifact_token. |
inspect_pdf | Free. Reports structural facts about one artifact: no new file is produced. | An artifact_id and an artifact_token for anonymous callers. | Page count, page sizes and rotations, and whether the PDF is encrypted, has form fields, annotations, outlines, embedded files or JavaScript. |
FileParts carry PDFs and CSVs as bytes or a URI; DataParts carry
structured arguments. A task that works on a form returns its form_id in a
DataPart, and a task that produced a file returns that file's artifact_id,
so a client can chain skills, such as make_fillable then fill_form, by id
without downloading anything in between. The free PDF tools, send_fax,
find_form, verify, read_form, attach and quote_job return no
form_id. See Artifacts and lineage. Filled PDFs and batch zips come
back as FileParts pointing at the same signed download link the REST API
serves.
prepare, commit and verify are the two-call flow: see
Prepare, commit and verify for the proposal
shape, the three results, and the receipt. read_form is the reverse of that
flow, see Read a filled form back; attach and
commit's package field hand over a finished submission as one file, see
The submission package.
Skills excluded from A2A on purpose: deleting a form stays on MCP and REST, where a client's own confirmation rules gate it, and usage lookups stay on the dashboard.
Task lifecycle and streaming
A task moves from submitted to working to completed or failed. A
request Emboss cannot run, such as an unknown skill, a missing form reference
or values that match no field, ends as a rejected task with the reason. A
paid skill called with no account waits in input-required until it is paid.
A 402 billing error, such as the free tier being used up, completes the task as
failed with the message and billing link. A connection that signed in with
read access only is rejected for any skill that changes something; reconnect
to allow changes.
Emboss supports streaming: a client that sends a streaming message or subscribes to a task receives status updates as the work happens, including one update per row for a batch fill, rather than only a single response at the end. Cancellation is honored before a task starts running, and while a paid task still waits for its payment: cancelling it withdraws the payment request, and nothing is charged. Once Emboss has begun the underlying job, it runs to completion.
Slower skills and checking a task
A skill whose job takes a while, such as making a new flat form fillable or filling a form from documents, answers within about 4 seconds either way:
- If the job finishes in that time, the answer carries the result as usual.
- If not, the answer is the task in state
working, with the message "Still running. Check this task in a few seconds for the result." The job keeps running. Check the task withtasks/get(GetTask) every few seconds until it ends (completed,failedorrejected). - A client holding a live stream gets a
workingupdate with the message "Still working." every 3 seconds, and the result arrives on the same stream.
Skills that answer at once, such as reading a filled form, suggesting a mapping and the free PDF utilities, answer with their result as before.
Checking a task returns one of:
working: the job is still running;completed, with the result the answer would have carried, such as the form id, the fields and a download link for a new fillable form. Two echoes of your request are not kept, so a check leaves them out: the valuesfill_formcould not match, and the mappingfill_batchused. The link stays the same however many times you check that day (UTC); a check on a later day gets a new one;failed, with the reason in the status message;rejected, with the reason, when the request could not be done, for example when none of the values sent tofill_formmatched a field.
For an account, ListTasks (A2A 1.0) with includeArtifacts: true lists its
own tasks with each task's result.
A job's files are kept for its retention period: about an hour with ephemeral processing, which every x402 job uses, or longer when an account keeps them. Once they are deleted, a completed task carries no result, and its status message reads "This result has expired: its files are deleted about an hour after the job."
Send a new message on a task only to answer it, for example to pay for it. A message on a task that is running or finished is refused with one of: "This task is still running; check it in a few seconds for the result.", "This task is finished; check it for the result.", or, for a task you paid for, "This task is paid; check it for the result." To get a result back, check the task: a new task is a new job, with a new price.
If we update Emboss while your job is running, the cut-off task is noticed
within about half an hour: after 15 minutes with no sign of life, on a check
that runs every 10 minutes. Then a job for an account starts again on its
own. This covers only these: making a form fillable (make_fillable),
filling from documents (fill_from_context) and preparing a form
(prepare). Each runs at most three times in all. Any other job cut off by
an update ends failed with a message that ends "Contact
contact@getemboss.ai with your task id.", and so does one of these cut off on
its third run. A job that had already finished when the update came is not
affected: its task shows how the job ended.
A fax or a batch is never sent or run again. A fax already with the carrier
is still delivered. A batch of more than 50 rows fills in the background
after its task has answered; if an update cuts it off, it is marked failed with the code
interrupted six hours after it started; send it again.
A job paid for with x402 never starts again. What its task says depends on the payment:
- If no payment could have been taken, the task ends
failedwith "Interrupted by maintenance; not charged. Send the request again." - If the payment was recorded and the job had run, the task carries its result and receipt as usual.
- Otherwise a payment may have been taken: the task ends
failedwith a message that ends "Contact contact@getemboss.ai with your task id." Write to that address with the task id rather than paying again on a new task.
Retention
make_fillable, fill_form, fill_from_context and prepare take an
optional retention DataPart field: ephemeral or account_default. Leave
it out and the account's own default applies. It applies only when the call
creates the form; an existing form keeps the setting it was created with.
fill_batch also accepts the field, but a batch always fills an existing form,
so there it changes nothing.
See Ephemeral processing for the window and
what a 410 means once a form is swept.
Limits
- A form PDF: up to 10 MB and 100 pages.
- Supporting documents for
fill_from_contextandprepare: up to 5 in all, countingcontext_textas one;context_textup to 200,000 characters; each linked or attached file up to 10 MB. fill_batch: up to 1,000 rows.- A proposal's attachments: up to 20 files and 20 MB in all.
Billing and privacy
Free tier: The first 5 form creations, 5 context fills, 5 standard fills, 5 verifications, 5 reads, and 5 packages each month are free when the job is 5 pages or fewer (a context fill counts the form and its documents together); a longer job is charged and does not use a free one. suggest_mapping is
billed as one context fill. See Pricing for current rates. Only
the arguments a task needs are sent to Emboss. If you connected Emboss with
OAuth, disconnect at any time from Dashboard, then Account, then
Connected apps.