# SDKs and HTTP clients
URL: https://backworkhealth.com/docs/sdks

Backwork has no published SDKs yet. Call the REST API with your language's HTTP client, or generate a typed client from the OpenAPI document.

Backwork does not publish SDKs yet. There is no Backwork package on PyPI, RubyGems or NuGet. The `@backwork/api` name on npm is an empty `0.0.0` placeholder, so do not install it.

The API is plain JSON over HTTPS, so any HTTP client works. You can also [generate a typed client](#generate-a-client) from the OpenAPI document.

## Call the API directly [#call-the-api-directly]

Every request needs a live key in the `Authorization` header. [Create one](https://backworkhealth.com/api-usage) with your organization's free starter credits. The examples read it from `BACKWORK_API_KEY`:

```bash
export BACKWORK_API_KEY=bwk_live_YOUR_API_KEY
```

Each example looks up CPT code 99213 with `GET /api/v1/codes/lookup`. It prints the code, its code system and whether Backwork found it. If the call fails, it prints the error code and message. A success response wraps the result in `data`; an error response has `success: false` and an `error` object. See [Errors](/docs/errors).

<Tabs items="[&#x22;cURL&#x22;, &#x22;Python&#x22;, &#x22;TypeScript&#x22;, &#x22;Ruby&#x22;, &#x22;Go&#x22;, &#x22;C#&#x22;]">
  <Tab value="cURL">
    ```bash
    curl "https://backworkhealth.com/api/v1/codes/lookup?code=99213" \
      -H "Authorization: Bearer $BACKWORK_API_KEY"
    ```
  </Tab>

  <Tab value="Python">
    Standard library only (`urllib.request`), Python 3.8+.

    ```python
    import json
    import os
    import urllib.error
    import urllib.request

    request = urllib.request.Request(
        "https://backworkhealth.com/api/v1/codes/lookup?code=99213",
        headers={"Authorization": f"Bearer {os.environ['BACKWORK_API_KEY']}"},
    )
    try:
        with urllib.request.urlopen(request) as response:
            body = json.load(response)
    except urllib.error.HTTPError as error:
        body = json.load(error)

    if body["success"]:
        print(body["data"]["code"], body["data"]["code_system"], body["data"]["found"])
    else:
        print(body["error"]["code"], body["error"]["message"])
    ```
  </Tab>

  <Tab value="TypeScript">
    Built-in `fetch`, Node.js 18+ as an ES module. The same code runs in Deno, Bun and edge runtimes.

    ```typescript
    const response = await fetch("https://backworkhealth.com/api/v1/codes/lookup?code=99213", {
      headers: { Authorization: `Bearer ${process.env.BACKWORK_API_KEY}` },
    });
    const body = await response.json();

    if (body.success) console.log(body.data.code, body.data.code_system, body.data.found);
    else console.log(body.error.code, body.error.message);
    ```
  </Tab>

  <Tab value="Ruby">
    Standard library only (`net/http`).

    ```ruby
    require "json"
    require "net/http"

    uri = URI("https://backworkhealth.com/api/v1/codes/lookup?code=99213")
    request = Net::HTTP::Get.new(uri)
    request["Authorization"] = "Bearer #{ENV.fetch('BACKWORK_API_KEY')}"
    response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") { |http| http.request(request) }
    body = JSON.parse(response.body)

    if body["success"]
      puts [body["data"]["code"], body["data"]["code_system"], body["data"]["found"]].join(" ")
    else
      puts [body["error"]["code"], body["error"]["message"]].join(" ")
    end
    ```
  </Tab>

  <Tab value="Go">
    Standard library only (`net/http`).

    ```go
    package main

    import (
    	"encoding/json"
    	"fmt"
    	"net/http"
    	"os"
    )

    func main() {
    	req, err := http.NewRequest("GET", "https://backworkhealth.com/api/v1/codes/lookup?code=99213", nil)
    	if err != nil {
    		panic(err)
    	}
    	req.Header.Set("Authorization", "Bearer "+os.Getenv("BACKWORK_API_KEY"))

    	resp, err := http.DefaultClient.Do(req)
    	if err != nil {
    		panic(err)
    	}
    	defer resp.Body.Close()

    	var body struct {
    		Success bool `json:"success"`
    		Data    struct {
    			Code       string `json:"code"`
    			CodeSystem string `json:"code_system"`
    			Found      bool   `json:"found"`
    		} `json:"data"`
    		Error struct {
    			Code    string `json:"code"`
    			Message string `json:"message"`
    		} `json:"error"`
    	}
    	if err := json.NewDecoder(resp.Body).Decode(&body); err != nil {
    		panic(err)
    	}

    	if body.Success {
    		fmt.Println(body.Data.Code, body.Data.CodeSystem, body.Data.Found)
    	} else {
    		fmt.Println(body.Error.Code, body.Error.Message)
    	}
    }
    ```
  </Tab>

  <Tab value="C#">
    `HttpClient` and `System.Text.Json`, .NET 8 top-level statements.

    ```csharp
    using System.Net.Http.Headers;
    using System.Text.Json;

    using var http = new HttpClient();
    http.DefaultRequestHeaders.Authorization =
        new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("BACKWORK_API_KEY"));

    using var response = await http.GetAsync("https://backworkhealth.com/api/v1/codes/lookup?code=99213");
    using var body = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
    var root = body.RootElement;

    if (root.GetProperty("success").GetBoolean())
    {
        var data = root.GetProperty("data");
        Console.WriteLine($"{data.GetProperty("code")} {data.GetProperty("code_system")} {data.GetProperty("found")}");
    }
    else
    {
        var error = root.GetProperty("error");
        Console.WriteLine($"{error.GetProperty("code")} {error.GetProperty("message")}");
    }
    ```
  </Tab>
</Tabs>

The [API reference](/docs/api) lists every endpoint, parameter and response field. Before you retry a failed call, check its `retryable` flag and the [rate limits](/docs/rate-limits).

## Generate a client [#generate-a-client]

The OpenAPI 3.1 document at `https://backworkhealth.com/openapi.json` describes every `/api/v1` endpoint. Generate a client from it and regenerate when the document changes.

### TypeScript: openapi-typescript [#typescript-openapi-typescript]

[openapi-typescript](https://openapi-ts.dev) turns the document into types, and [openapi-fetch](https://openapi-ts.dev/openapi-fetch/) makes typed calls with them:

```bash
npm install openapi-fetch
npx openapi-typescript https://backworkhealth.com/openapi.json -o backwork.d.ts
```

```typescript
import createClient from "openapi-fetch";

import type { paths } from "./backwork.d.ts";

const backwork = createClient<paths>({
  baseUrl: "https://backworkhealth.com/api/v1",
  headers: { Authorization: `Bearer ${process.env.BACKWORK_API_KEY}` },
});

const { data, error } = await backwork.GET("/codes/lookup", { params: { query: { code: "99213" } } });
if (data) console.log(data.data.code, data.data.code_system, data.data.found);
else console.log(error.error.code, error.error.message);
```

### Other languages: OpenAPI Generator [#other-languages-openapi-generator]

[OpenAPI Generator](https://openapi-generator.tech) reads the document and emits clients for Python, Ruby, Go, C#, Java and [many more](https://openapi-generator.tech/docs/generators):

```bash
docker run --rm -v "$PWD:/local" openapitools/openapi-generator-cli:v7.12.0 generate \
  -i https://backworkhealth.com/openapi.json \
  -g python \
  -o /local/backwork-client
```

Swap `-g python` for `ruby`, `go`, `csharp` or `java`. Generated method names follow each endpoint's `operationId`, such as `lookupCode`.

<Callout type="warn" title="Test the generated client before you rely on it">
  The generated Python client rejects every successful response: it reads `success: true` as a string enum. The generated Go client does not compile. For those languages, use the direct HTTP examples above until Backwork publishes SDKs.
</Callout>

## Command line [#command-line]

The [Backwork CLI](/docs/sdks/go) is a single Go binary for lookups from a terminal or a script.

## Use Backwork from an AI assistant [#use-backwork-from-an-ai-assistant]

The [MCP server](/docs/mcp) connects Claude and other MCP clients to Backwork with no code.
