> ## Documentation Index
> Fetch the complete documentation index at: https://vaquill.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# SDKs overview

> Official Python, TypeScript, Go, Java and Kotlin clients and framework integrations for the Vaquill Data API

The Vaquill SDKs are typed clients for the US Data API.
They wrap the same endpoints described in this guide and add retries, typed errors, pagination helpers and credit awareness.
Anything an SDK can do, you can also do with plain HTTP.

| Package | Language | Install | Status | Source |
| - | - | - | - | - |
| `vaquill` | Python 3.11+ | `pip install vaquill` | Published (0.2.1 on PyPI) | [`Vaquill-AI/vaquill-sdks`, `python/`](https://github.com/Vaquill-AI/vaquill-sdks/tree/main/python) on GitHub |
| `@vaquill-ai/sdk` | TypeScript, Node 20+ (built on standard `fetch`; tested on Node 20, 22 and 24) | `npm install @vaquill-ai/sdk` | Published (0.2.1 on npm) | [`Vaquill-AI/vaquill-sdks`, `js/`](https://github.com/Vaquill-AI/vaquill-sdks/tree/main/js) on GitHub |
| `vaquill` CLI | Command line | See [CLI](https://vaquill.ai/docs/api-guide/sdks/cli.md) | Published, inside the Python package | Same repos |
| `github.com/Vaquill-AI/vaquill-sdks/go` | [Go](https://vaquill.ai/docs/api-guide/sdks/go.md) 1.23+ | `go get` (v0.1.0) | [pkg.go.dev](https://pkg.go.dev/github.com/Vaquill-AI/vaquill-sdks/go) | [`go/`](https://github.com/Vaquill-AI/vaquill-sdks/tree/main/go) |
| `ai.vaquill:vaquill-sdk` | [Java](https://vaquill.ai/docs/api-guide/sdks/java.md) 11+ | Not yet published | Not yet published | [`java/`](https://github.com/Vaquill-AI/vaquill-sdks/tree/main/java) |
| `ai.vaquill:vaquill-kotlin` | [Kotlin](https://vaquill.ai/docs/api-guide/sdks/kotlin.md) (JVM 11+) | Not yet published | Not yet published | [`kotlin/`](https://github.com/Vaquill-AI/vaquill-sdks/tree/main/kotlin) |
| `langchain-vaquill`, `llama-index-tools-vaquill`, `@vaquill-ai/ai-sdk` | [Framework integrations](https://vaquill.ai/docs/api-guide/sdks/integrations.md) (LangChain, LlamaIndex, Vercel AI SDK) | `pip install langchain-vaquill`, `pip install llama-index-tools-vaquill` (`@vaquill-ai/ai-sdk` not yet published) | LangChain and LlamaIndex published (0.1.0 on PyPI) | [`integrations/`](https://github.com/Vaquill-AI/vaquill-sdks/tree/main/integrations) |

The Java, Kotlin and Vercel AI packages are not on any registry yet. Their pages show the intended coordinates and how to build from source.

All SDKs are MIT licensed.
The data you retrieve is covered by separate terms. See [Rights and licensing](https://vaquill.ai/docs/api-guide/rights-and-licensing.md).

> [!NOTE]
>
> The SDKs cover the US document only. For India, use the separate OpenAPI document directly.

## Authentication

Create a key in your [dashboard](https://app.vaquill.ai/settings) under **API Keys**. Keys start with `vq_key_`.

By default the client reads `VAQUILL_API_KEY` from the environment.
You can also pass `api_key` (Python) or `apiKey` (TypeScript) explicitly, and an explicit value wins over the environment.
The client rejects a key that does not start with `vq_key_`, and the key never appears in an error message or a log line.

> [!WARNING]
>
> Use the SDKs server-side only. A key shipped in browser code is visible to every visitor. The TypeScript client warns when it sees a browser.

## Configuration

| Option | Python | TypeScript | Environment variable |
| - | - | - | - |
| API key | `api_key` | `apiKey` | `VAQUILL_API_KEY` |
| Base URL | `base_url` | `baseURL` | `VAQUILL_BASE_URL` |
| Timeout | `timeout` (seconds, per attempt) | `timeout` (milliseconds, per attempt) | none |
| Maximum retries (default 2) | `max_retries` | `maxRetries` | none |
| Extra headers | `default_headers` | `defaultHeaders` | none |
| Spend guard | `max_credits` | `maxCredits` | none |
| Custom HTTP | `http_client` (an `httpx.Client`) | `fetch` | none |

`client.with_options(...)` (Python) and `client.withOptions({ ... })` (TypeScript) return a derived client that shares the key and the spend counter.
Every method also takes per-call `timeout`, `max_retries` / `maxRetries`, `headers` and `idempotency_key` / `idempotencyKey` options.

## Which calls cost credits

A call is charged when the API declares the `Idempotency-Key` header on its operation. That is 25 of the 36 operations in the US document.
Both SDKs apply the same rule, and a test in each repo derives the list from the API contract.
Free calls: `statutes.coverage`, `boards.list`, every watch operation except the change diff (`create`, `list`, `update`, `delete`, `test`, changes and deliveries), `credits.balance` and `pricing.get`.
Prices are not hard-coded in the SDKs. `client.pricing.get()` is free and returns the live price list.
Some charged calls return 0 credits (for example a body that is not held), so read the figure from the response.

## Retries and timeouts

The clients retry 408, 429 and 5xx responses, plus 409 only for `idempotency_in_progress`. Connection errors and timeouts are retried when it is safe.
Backoff starts at 0.5 seconds, doubles to an 8 second cap and is scaled down by 0 to 25 percent jitter. The default is 2 retries; `max_retries=0` / `maxRetries: 0` turns them off.
`retry-after-ms` wins over `Retry-After`, which wins over the body's `retryAfterSeconds`. A wait above 120 seconds is not retried.

Never retried: a 402 `insufficient_credits`, `daily_cap_exceeded`, any other 4xx, and anything the server marks `retryable: false`.

## Idempotency

Each charged call sends one generated `Idempotency-Key`, reused on every retry of that call.
When the server honours the key it replays the stored response instead of charging again, and the response reports `idempotent_replayed` / `idempotentReplayed`.
Pass `idempotency_key="..."` (Python) or `idempotencyKey: "..."` (TypeScript) to choose your own key.

> [!WARNING]
>
> If you turn automatic keys off (`idempotency_keys=False` in Python, `idempotencyKey: false` in TypeScript), a charged call is no longer retried after a timeout, a connection error or a 5xx, because the first attempt may already have been billed. A 429 is still retried, since it is refused before any work.
> Free `POST`s without a key (`watches.create`, `watches.test`) follow the same rule, so a retry cannot create a second watch.

## Errors

Every error derives from `VaquillError`. Status errors carry the HTTP status, the request id, the parsed body, and `code`, `retryable` and a retry hint when the server sends them.

| Class | When |
| - | - |
| `APIConnectionError` | The request never got a response. `APITimeoutError` is a timeout (TypeScript adds `APIUserAbortError`). |
| `BadRequestError` | 400 |
| `AuthenticationError` | 401 |
| `InsufficientCreditsError` | 402. Never retried. |
| `PermissionDeniedError` | 403 |
| `NotFoundError` | 404 |
| `ConflictError` | 409 |
| `UnprocessableEntityError` | 422 |
| `RateLimitError` | 429. `DailyCapExceededError` is the per-key daily cap and cannot succeed until it resets. |
| `InternalServerError` | 5xx |
| `IdempotencyConflictError` | Idempotency failures: `IdempotencyKeyReusedError`, `IdempotencyInProgressError`, `IdempotencyReplayUnavailableError` |
| `SpendGuardExceeded` (Python), `SpendGuardExceededError` (TypeScript) | The spend guard stopped a charged call before it was sent |
| `ResponseParseError` | A 2xx response whose body was not the JSON the endpoint promises |
| `WebhookVerificationError` | A webhook delivery failed verification |

The code is checked first, then the status, so an unknown code still gives the status class.
A 422 message ends with the first validation reasons from the response's `errors` list, so you can read what was rejected without opening the body.
See [Errors](https://vaquill.ai/docs/api-guide/errors.md) for the wire format.

## Pagination

Python `iter_*` helpers and TypeScript `*All` methods hide the offset, cursor and `sinceId`/`beforeId` styles behind one iterator, with a way to read whole pages.

> [!WARNING]
>
> On a charged endpoint every page spends credits. Iterating a whole result set can cost far more than one call.
> Set `max_pages` / `maxPages` or `max_items` / `maxItems`, or use the spend guard. Without a limit a TypeScript iterator runs until the data ends.
> The Python pager reports `truncated` when its guard stopped it with more data available.

Listing watches, changes and boards is free.

## Batch helpers

Three helpers wrap the batch endpoints and accept any number of inputs: `resolve_batch_all` / `resolveBatchAll` (500 citations per request), `get_sections_all` / `getSectionsAll` (50 section ids) and `session_laws.get_batch_all` / `sessionLaws.getBatchAll` (200 ids).
Each splits the input at the per-call cap, sends exact repeats once, returns the members of every response as one flat list in input order, and sends nothing for an empty input.
The spend guard is checked before every chunk, so a guard reached part way stops the remaining chunks.
A caller's idempotency key is kept for the first chunk and suffixed with `-<chunk number>` for later ones.
These helpers are charged per item. The batch helpers are available in the Python, TypeScript, Go, Java and Kotlin clients.

## Spend guard

Pass `max_credits` (Python) or `maxCredits` (TypeScript) when you create the client. Once responses on that client have reported that many credits, charged calls raise `SpendGuardExceeded` / throw `SpendGuardExceededError` before sending anything.
It checks what is already spent, not the cost of the next call. `client.credits_spent` / `client.creditsSpent` shows the running total, shared with derived clients.
While a guard is set, charged calls on the client run one at a time, from the check to the moment their credits are counted, so concurrent calls cannot all pass the check and overshoot the cap. Without a guard, calls keep full concurrency.

## Logging

Python logs through the standard `logging` module under the `vaquill` logger.
TypeScript takes a `logger` option (any subset of `debug`, `info`, `warn` and `error`, default `console`) and a `logLevel` option (default `warn`).
The API key is always redacted, and idempotency keys are logged by their first 8 characters only.

## Raw responses

Python: `client.with_raw_response.request(...)` returns the parsed body with `request_id`, `rate_limit` and `credits_charged_this_call`.
TypeScript: `.withResponse()` on any call returns `{ data, response, meta }`.
Both clients also have `raw_request` / `rawRequest` for endpoints newer than the SDK.
Python's `raw_request` returns an `APIResponse`, so call `.parse()` for the JSON body.
TypeScript's `rawRequest` returns the parsed value directly.

## Webhook verification

Both SDKs verify the raw request body against the Standard Webhooks headers (`webhook-id`, `webhook-timestamp`, `webhook-signature`) with a 300 second tolerance, accept several signatures and a list of secrets for rotation, and treat a `whsec_` secret as base64.
A `whsec_` secret must be valid base64. Go, Java and Kotlin reject one that is not.
Python and TypeScript reject it from the first release after 0.2.0; version 0.2.0 of both still uses the text as the key, so check that your secret is copied in full.
Every client rejects an empty secret.
They can also read the legacy `X-Vaquill-Signature: sha256=<hex>` header, but only when you opt in.

> [!WARNING]
>
> The legacy header signs only the body, so it has no replay protection: a captured delivery verifies forever.
> Both SDKs reject it unless you set `allow_legacy=True` (Python) or `allowLegacy: true` (TypeScript).

## Types

Python responses are Pydantic v2 models and the package ships `py.typed`. TypeScript types are generated from the OpenAPI document.
Unknown enum values and extra response fields do not raise, so a new corpus type or field will not break an older SDK.
Python uses snake\_case names and TypeScript uses camelCase. The SDK maps them to the wire names for you.

## Versioning and support

* SDKs follow semantic versioning. Before 1.0, the API surface may change in minor versions.
* The SDK major version tracks the major version of the API contract.
* Python 0.2.1, TypeScript 0.2.1, Go 0.1.0, `langchain-vaquill` 0.1.0 and `llama-index-tools-vaquill` 0.1.0 are the published versions. Java, Kotlin and `@vaquill-ai/ai-sdk` are at 0.1.0 in source and unpublished.
* Python 3.11 and later are supported. Node 20 and later are supported, and the TypeScript client is tested on Node 20, 22 and 24.
* Breaking changes are listed in the release notes.
* Report bugs on the issue tracker of the [vaquill-sdks repository](https://github.com/Vaquill-AI/vaquill-sdks/issues). For account or billing questions, email support.

## Next steps

> **[Python](https://vaquill.ai/docs/api-guide/sdks/python.md)**
>
> Install, quickstart, async and error handling

> **[TypeScript](https://vaquill.ai/docs/api-guide/sdks/typescript.md)**
>
> Install, quickstart and error handling

> **[Go](https://vaquill.ai/docs/api-guide/sdks/go.md)**
>
> Install with go get, quickstart and error handling

> **[Java and Kotlin](https://vaquill.ai/docs/api-guide/sdks/java.md)**
>
> Not yet published. Intended coordinates and build from source: [Java](https://vaquill.ai/docs/api-guide/sdks/java.md), [Kotlin](https://vaquill.ai/docs/api-guide/sdks/kotlin.md)

> **[Integrations](https://vaquill.ai/docs/api-guide/sdks/integrations.md)**
>
> LangChain and LlamaIndex tools (published) and Vercel AI SDK tools (not yet published)

> **[CLI](https://vaquill.ai/docs/api-guide/sdks/cli.md)**
>
> Search and resolve from the shell

> **[API Reference](https://vaquill.ai/docs/api-reference/us-statutes/search-us-statutes-constitutions-court-rules-and-executive-actions.md)**
>
> Every endpoint and schema


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.