Warddocs
Client SDKs

Python SDK

pip install mandate-ward
export WARD_API_KEY="ward_test_..."
from ward import Ward

client = Ward()                                   # or Ward(api_key="...", timeout=60, max_retries=2)
d = client.decide("screen", {"name": "Ana Maria Perez", "country": "PAN"})
print(d.decision, d.score, d.signals)             # attribute or key access: d["decision"]

Async

import asyncio
from ward import AsyncWard

async def main():
    async with AsyncWard() as client:
        d = await client.decide("payment", {"amount": 120, "currency": "USD", "mcc": "5411"})

asyncio.run(main())

Methods

Method Endpoint
decide(type, input, *, model, subject_ref, subject_consent, session_id, policy_baseline, run_async, idempotency_key, timeout) POST /decide
statement(files, *, profile, focus, thresholds, column_map, …) POST /decide (statement)
credit(files, *, profile, requested_instalment, …) POST /decide (credit)
screen(name, *, date_of_birth, country, entity_type) POST /decide (screen)
ask(question, *, decision=None, result=None, context=None, session_id=None) POST /ask
feedback(decision_id, *, correct, right_decision, label, threshold, note) POST /decide/{id}/feedback
get_decision(id), evidence(id), session(id) GET /decide/{id}, /evidence, /sessions/{id}
models(), balance(), usage(days=30) GET /models, /billing/*
kyc.send_code(channel, destination), kyc.confirm_code(challenge_id, code) POST /kyc/otp/*
kyc.verify(applicant, *, email_challenge_id, phone_challenge_id, policy, locale) POST /kyc/verify
kyc.outcome(verification_id, outcome), kyc.check_email(email), kyc.check_phone(phone) POST /kyc/outcomes, /email/check, /phone/check
kyc.network_auth_start(phone, redirect_uri), kyc.network_auth_complete(state, code) POST /kyc/network-auth/*
jobs.get(id), jobs.wait(id, timeout=300) GET /jobs/{id}
subjects.get(ref), subjects.update(ref, **fields), subjects.delete(ref) /subjects/{ref}

statement() and credit() take paths, bytes, (name, bytes) tuples or ready {"file_base64", "file_name"} dicts.

Errors

import ward

try:
    d = client.decide("statement", inp)
except ward.UnprocessableEntityError as e:
    if e.code == "needs_mapping":
        reading = e.details["reading"]            # show it, then resend with column_map
except ward.InsufficientBalanceError:
    top_up()
except ward.APIError as e:
    log.error("ward %s %s (request %s)", e.status, e.code, e.request_id)
Class Status
AuthenticationError 401
InsufficientBalanceError 402
PermissionDeniedError 403
NotFoundError 404
ConflictError 409
PayloadTooLargeError 413
UnprocessableEntityError 422
RateLimitError 429
InternalServerError 5xx
APIConnectionError, APITimeoutError no response

All inherit from ward.WardError. Configuration: WARD_API_KEY, WARD_BASE_URL (default https://api.mandatelabs.ai/api/v1).