WorkbookAPI

Quickstart

1. Create an account and key

Sign up, confirm your email, then open API keys and create an admin key. Your trial gives you 14 days, 1 model and 1,000 scenarios, no card.

Keep the key on your server. Set WORKBOOKAPI_KEY to it in your terminal. Never put a key in a browser, a URL or source control. Use a calculate-only key for production apps; the admin key below is for setup.

These commands need curl and Python 3, with no Python packages. Start by setting the API base URL below. Every request below uses a timeout of 90 seconds.

export WBAPI_BASE_URL=https://api.workbookapi.com

2. Upload the sample

The browser check is private. This next step deliberately uploads the sample loan model to the hosted API.

curl --fail-with-body --silent --show-error --max-time 90 \
  https://workbookapi.com/sample/loan-model.xlsx --output loan-model.xlsx
curl --fail-with-body --silent --show-error --max-time 90 \
  "$WBAPI_BASE_URL/v1/models" \
  -H "Authorization: Bearer $WORKBOOKAPI_KEY" \
  -F file=@loan-model.xlsx --output uploaded.json --write-out 'HTTP %{http_code}\n'
export MODEL_ID=$(python3 -I -c 'import json; print(json.load(open("uploaded.json"))["model_id"])')

A successful upload returns HTTP 201 with model_id, version_id, report and request_id. The command saves the response and sets MODEL_ID. IDs vary for each upload.

3. Declare inputs and outputs

Give each input and output an API name. This sample uses cells; for your own workbooks, prefer defined names in ref, so a new version survives moved cells.

curl --fail-with-body --silent --show-error --max-time 90 \
  -X PUT "$WBAPI_BASE_URL/v1/models/$MODEL_ID/interface" \
  -H "Authorization: Bearer $WORKBOOKAPI_KEY" \
  -H "Content-Type: application/json" \
  --data '{"inputs":[{"name":"principal","ref":"Inputs!B2","type":"number","min":1000,"max":10000000},{"name":"rate","ref":"Inputs!B3","type":"number","min":0,"max":1},{"name":"term_months","ref":"Inputs!B4","type":"number","allowed":[120,180,240,360]}],"outputs":[{"name":"monthly_payment","ref":"Summary!B2"}]}' \
  --output interface.json --write-out 'HTTP %{http_code}\n'

HTTP 200 returns interface with the declared inputs and outputs, plus model_id, version_id and request_id.

4. Calculate with curl

curl --fail-with-body --silent --show-error --max-time 90 \
  "$WBAPI_BASE_URL/v1/models/$MODEL_ID/calculate" \
  -H "Authorization: Bearer $WORKBOOKAPI_KEY" \
  -H "Content-Type: application/json" \
  --data '{"inputs":{"principal":250000,"rate":0.045,"term_months":360}}' \
  --output calculated.json --write-out 'HTTP %{http_code}\n'
python3 -I -c 'import json; r=json.load(open("calculated.json")); assert type(r["outputs"]["monthly_payment"]) in (int, float); print("Calculation returned a monthly payment.")'

Expected terminal output:

HTTP 200
Calculation returned a monthly payment.

HTTP 200 includes outputs.monthly_payment as a number, billed_scenarios: 1, warnings, request_id, model_id, version_id and engine_build. The full-precision amount is in calculated.json. Each calculation starts from the saved inputs; omitted inputs keep their workbook values.

5. Calculate with Python

Keep MODEL_ID, WORKBOOKAPI_KEY and WBAPI_BASE_URL set. Save this as calculate.py and run python3 -I calculate.py. It calls the same model and prints the same line.

import json
import os
import urllib.request

url = os.environ["WBAPI_BASE_URL"].rstrip("/") + "/v1/models/" + os.environ["MODEL_ID"] + "/calculate"
body = json.dumps({"inputs": {"principal": 250000, "rate": 0.045, "term_months": 360}}).encode()
request = urllib.request.Request(url, data=body, headers={
    "Authorization": "Bearer " + os.environ["WORKBOOKAPI_KEY"],
    "Content-Type": "application/json",
})
with urllib.request.urlopen(request, timeout=90) as response:
    assert response.status == 200
    result = json.load(response)
assert type(result["outputs"]["monthly_payment"]) in (int, float)
print("Calculation returned a monthly payment.")

Next steps

Use scenarios for batches, upload a new version under the same model ID, or choose output names on each call. Read the API reference and limits. A client timeout can cut off an already billed response; a retry counts again.