Run a Simulation
Submit every argument and response in one call with
POST /api/v1/simulations,
then poll
GET /api/v1/simulations/{id}
until status
is ready.
result_url
and the result's
pdf_url
are the public award PDF.
page_url
opens the simulation page only when the key owner is signed in
on the web. Fetch the award text, plus that PDF URL, from
GET /api/v1/simulations/{id}/result.
This requires a production API key. Test keys receive
403.
A simulation id shares the case_
prefix but is not a /cases
resource. GET /api/v1/simulations
lists the simulations your key owns, newest first, if you lose
an id.
The script sends a fresh
Idempotency-Key.
The token is scoped to that API key. The same token on another
key, including a test key, is a new reservation. Reuse a key only
to retry the same body: the same body replays the stored result,
and a different body is
409.
A retry is
409
while this key holds the lease. An abandoned attempt can be
reused after the lease expires, about a minute.
-
1
Create a production API key at /settings/api-keys. Keys from /settings/test-api-keys cannot run simulations.
-
2
Install the only dependency:
pip install requests -
3
Paste your key into the script below (replace
PASTE_YOUR_KEY_HERE) and runpython run_simulation.py.
Authenticate every request with a production bearer token:
Authorization: Bearer dvarb_your_key_here
run_simulation.py
"""DecisionLayer API example: run a simulation in one request.
Simulations require a production API key (dvarb_...). A test key
(dvarb_test_...) receives 403. Create a production key at
https://www.decisionlayer.ai/settings/api-keys
The script sends a fresh Idempotency-Key. That token is scoped to this
API key. The same token on another key, including a test key, is a new
reservation. Reuse a key only to retry the same body: the same body
replays the stored result, and a different body is 409. A retry is 409
while the key holds the lease. An abandoned attempt can be reused after
the lease expires, about a minute.
Then run:
pip install requests
python run_simulation.py
"""
import time
import uuid
import requests
# 1. Paste your production API key here (from /settings/api-keys).
API_KEY = "PASTE_YOUR_KEY_HERE"
# 2. Base URL of the DecisionLayer API. Use http://localhost:8000 locally.
BASE_URL = "https://www.decisionlayer.ai"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
def main() -> None:
# One multipart request files the contract and every round. Files under
# 8 MiB go in the file fields below. At 8 MiB or larger, POST
# /api/v1/uploads, PUT the bytes, and send contract_file_ticket or
# plaintiff_documents_tickets (and the other *_tickets fields) instead.
data = {
"question_for_arbitration": "Did the respondent owe the deposit back?",
"governing_contract": (
"The parties agreed that any dispute over the deposit would be "
"decided in arbitration, and that the deposit is refundable if "
"the work was not delivered within 30 days."
),
"financial_demand_usd": "3500.00",
"plaintiff_name": "Avery Quinn",
"respondent_name": "Jordan Chen",
"plaintiff_argument": (
"The contract required the deposit to be returned within 30 days "
"if delivery slipped. Delivery slipped, and the deposit was kept."
),
"respondent_argument": (
"Delivery was late because the claimant changed the scope. The "
"deposit was earned."
),
"plaintiff_rebuttal": "The scope change was never agreed in writing.",
"respondent_rebuttal": "The emails of March 2 accepted the new scope.",
}
# requests sends application/x-www-form-urlencoded when files= is omitted.
# This endpoint is multipart even when every attachment is text, so pass
# an empty file part. A blank filename is ignored.
#
# A fresh key files a new simulation. Reuse one only to retry this body.
# The token is scoped to this API key. The same body replays; a different
# body is 409. A retry is 409 while the lease is held. An abandoned
# attempt can be reused after the lease expires, about a minute.
response = requests.post(
f"{BASE_URL}/api/v1/simulations",
headers={**HEADERS, "Idempotency-Key": str(uuid.uuid4())},
data=data,
files={"contract_file": ("", b"", "application/octet-stream")},
timeout=60,
)
if response.status_code != 201:
print(f"Request failed ({response.status_code}):")
print(response.json())
raise SystemExit(1)
created = response.json()
# The id shares the case_ prefix but is not a /cases resource. If you
# lose it, GET /api/v1/simulations lists the ones this key owns.
simulation_id = created["id"]
print(f"Queued simulation: {simulation_id}")
print(f"Status: {created['status']}")
print(f"Page: {created['page_url']}")
# Poll until the award is public. A run usually finishes in a few minutes.
for _attempt in range(60):
status = requests.get(
f"{BASE_URL}/api/v1/simulations/{simulation_id}",
headers=HEADERS,
timeout=60,
)
status.raise_for_status()
body = status.json()
print(f"Status: {body['status']}")
if body["status"] == "failed":
print(body.get("message"))
raise SystemExit(1)
if body["status"] == "ready":
result = requests.get(
f"{BASE_URL}/api/v1/simulations/{simulation_id}/result",
headers=HEADERS,
timeout=60,
)
result.raise_for_status()
award = result.json()
print(f"Result URL: {award['pdf_url']}")
print(f"Page: {award['page_url']}")
print(award["text"])
return
time.sleep(10)
print("Still running. Poll GET /api/v1/simulations/{id} and then GET .../result.")
print("GET /api/v1/simulations lists your simulations if you lose the id.")
if __name__ == "__main__":
main()