Bearer key · JSON
POST /api/v1/sheets/build
curl -s -X POST https://getattest.com.au/api/v1/sheets/build \
-H "authorization: Bearer $ATTEST_API_KEY" \
-H "content-type: application/json" \
-d '{"format":"csv","sheets":[{"name":"Invoices","columns":[{"key":"ref","label":"Reference","type":"text"},{"key":"total","label":"Total","type":"currency"}],"rows":[{"ref":"INV-1001","total":249.5}]}]}'
Send the key as a bearer token in the authorization header. One key and one credit balance cover every service, including Attest Capture. A failed call is refunded automatically. No key yet? POST /api/v1/keys issues one with 25 free credits and no signup — see the key guide.
Captured 2026-09-21
Example
This request was run against the running service on 2026-09-21 and the response below is what came back, unedited.
Request JSON
{
"format": "csv",
"sheets": [
{
"name": "Invoices",
"columns": [
{
"key": "ref",
"label": "Reference",
"type": "text"
},
{
"key": "total",
"label": "Total",
"type": "currency"
}
],
"rows": [
{
"ref": "INV-1001",
"total": 249.5
}
]
}
]
}
Captured response JSON
{
"call_id": "1d3447e5-a30e-41e9-8d6c-9da5421c9b6d",
"format": "csv",
"content_type": "text/csv; charset=utf-8",
"filename": "Invoices.csv",
"sheets": [
{
"name": "Invoices",
"rows": 1,
"columns": 2
}
],
"cells_written": 4,
"cells_repaired": 0,
"formula_guard": {
"guarded_cells": 0,
"triggers": [
"=",
"+",
"-",
"@",
"tab",
"cr"
],
"method": "apostrophe_prefix",
"note": "CSV has no cell formats, so a value starting with =, +, -, @, a tab or a carriage return is given a literal leading apostrophe. This is the one case where a value in the file differs from the value sent."
},
"dates": "Dates are written as the ISO 8601 text that was sent, because a CSV has no date format to apply.",
"text_storage": "Text is written as sent. A field holding a comma, a double quote or a line break is wrapped in double quotes with its own quotes doubled, per RFC 4180.",
"bytes": 36,
"sha256": "2ce8e6aee271b49a365677cedf4385f42dfad7fe33ce55e17933ba24755643c6",
"file_base64": "77u/UmVmZXJlbmNlLFRvdGFsDQpJTlYtMTAwMSwyNDkuNQ0K",
"source": "The file contains only the values supplied in the request. Nothing is looked up, calculated or added, and no copy of the data is kept after the response is sent.",
"checked_at": "2026-09-20T16:55:57.508Z",
"credits_charged": 1,
"credits_remaining": 9990
}
For agents
Use when
Use this when a task has to hand back a real spreadsheet rather than a wall of rows: typed columns (text, number, date, currency, percent) with number formats applied, a bold header, optional frozen header row, column widths and an autofilter, returned as a base64 .xlsx or .csv. Up to 10 sheets and 50,000 cells in total (the header row counts). Values that could be read back as formulas are neutralised. Dates go in as YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS; percent cells store a fraction (0.15 is 15%) unless the column sets percent_basis to "percent". CSV takes one sheet.
4 fields
Input
Scroll the table horizontally to see all fields.
Field / Type / Required / What it does| Field | Type | Required | What it does |
|---|
format | string | Optional | xlsx (default) or csv. CSV takes one sheet. |
|---|
sheets | array | Required | Up to 10 sheets. Each has a name, a columns list and an optional rows list, plus freeze_header and autofilter flags. |
|---|
sheets[].columns | array | Required | Each column: key, label and type (text, number, date, currency, percent), with optional width and percent_basis. |
|---|
sheets[].rows | array | Optional | Each row is an object keyed by column key. Up to 50,000 cells in total, header row included. |
|---|
HTTP 200
Response
Every successful response also carries call_id (your receipt for the charge), credits_charged and credits_remaining.
Scroll the table horizontally to see all fields.
Field / What it holds| Field | What it holds |
|---|
format | The format produced. |
|---|
content_type | The media type of the produced file. |
|---|
filename | A suggested file name. |
|---|
sheets | Each sheet with its row and column counts. |
|---|
cells_written | Cells written. |
|---|
cells_repaired | Cells where characters no XML document can hold were dropped. |
|---|
formula_guard | How many cells carry the formula guard, what triggers it and how it is applied. |
|---|
dates | How dates are stored in this format. |
|---|
text_storage | How text is stored in this format. |
|---|
bytes | Size of the produced file. |
|---|
sha256 | SHA-256 of the produced bytes. The same rows always produce the same hash. |
|---|
file_base64 | The produced file. |
|---|
Machine-readable failures
Errors
Errors return JSON such as {"error":"invalid_api_key"}. A failed call is refunded automatically.
Scroll the table horizontally to see all fields.
Code / Status / Meaning| Code | Status | Meaning |
|---|
sheets_required | 400 | No sheets were sent. |
|---|
invalid_format | 400 | format is not xlsx or csv. |
|---|
csv_multiple_sheets | 400 | More than one sheet was sent with format csv. |
|---|
too_many_sheets | 400 | More than 10 sheets were sent. |
|---|
columns_required | 400 | A sheet has no columns. |
|---|
too_many_columns | 400 | A sheet has more columns than the cap. |
|---|
too_many_rows | 400 | A sheet has more rows than the cap. |
|---|
too_many_cells | 400 | The workbook is past the 50,000-cell cap. |
|---|
input_too_large | 400 | The text across all cells is past the character cap. |
|---|
output_too_large | 413 | The finished file is past the response cap; split the job. |
|---|
On every service
Scroll the table horizontally to see all fields.
Code / Status / Meaning| Code | Status | Meaning |
|---|
invalid_api_key | 401 | The authorization header is missing or the key is unknown. |
|---|
insufficient_credits | 402 | The balance is below this call's cost. The response carries credits_required and credits_remaining. |
|---|
rate_limit_exceeded | 429 | Free keys share 10 calls a minute across every service. The response carries limit and window_seconds. |
|---|
services_unavailable | 503 | The credit store could not be reached. Retry once after 30 seconds. |
|---|
4 worked examples
Examples
Where the answer comes from
Source and scope
The file contains only the values supplied in the request. Nothing is looked up, calculated or added, and no copy of the data is kept after the response is sent. Written against ECMA-376.
Attest reports what it read, with the source it read it from. It is general information, not advice, and not a legal record.
All Attest tools · Service list as JSON · OpenAPI