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

# Making Requests

> Code examples for calling the BillReview API in cURL, Node.js, Python, Ruby, PHP, and C#.

Include the access token and your API key on every request. The examples below use gzip compression for the request body, which is **recommended for production** at volume. Plain JSON is also accepted today — see [Authentication](/authentication) for details. Gzip compression will be required in a future version of the API.

<Note>
  The examples below are simplified for clarity. For production use — with token caching and automatic 401 retry — see [Token Lifecycle](/token-lifecycle).
</Note>

<CodeGroup>
  ```bash cURL theme={null}
  # Compress the JSON payload and pipe directly to curl
  printf '{"controlNumber":"12345","billType":"professional","jurisdiction":"CA","providerTaxId":"123456789","providerZip":"90210","lines":[{"lineNumber":1,"cpt":"99213","serviceDate":"2025-07-15","charge":175.00,"units":1}]}' \
    | gzip -c \
    | curl -X POST {your_api_endpoint}/v1/review \
        -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
        -H "x-api-key: {your_api_key}" \
        -H "Content-Type: application/json" \
        -H "Content-Encoding: gzip" \
        --data-binary @- \
        --compressed
  ```

  ```js Node.js theme={null}
  import { gzipSync } from 'zlib';

  const tokenRes = await fetch(TOKEN_URL, {
    method: "POST",
    headers: {
      "Authorization": "Basic " + Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString("base64"),
    },
  });
  const { access_token } = await tokenRes.json();

  // Compress the JSON body — the API gateway forwards Content-Encoding: gzip unchanged
  const compressed = gzipSync(Buffer.from(JSON.stringify(billPayload)));

  const reviewRes = await fetch(`${API_ENDPOINT}/v1/review`, {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${access_token}`,
      "x-api-key": API_KEY,
      "Content-Type": "application/json",
      "Content-Encoding": "gzip",
    },
    body: compressed,
  });
  // Node.js fetch automatically decompresses the gzip response
  const result = await reviewRes.json();
  ```

  ```python Python theme={null}
  import requests, base64, gzip, json

  credentials = base64.b64encode(f"{CLIENT_ID}:{CLIENT_SECRET}".encode()).decode()
  token_res = requests.post(
      TOKEN_URL,
      headers={"Authorization": f"Basic {credentials}"},
  )
  access_token = token_res.json()["access_token"]

  # Compress the JSON body — use data= (not json=) since we're sending raw compressed bytes
  # The API gateway forwards Content-Encoding: gzip unchanged
  compressed = gzip.compress(json.dumps(bill_payload).encode())

  review_res = requests.post(
      f"{API_ENDPOINT}/v1/review",
      headers={
          "Authorization": f"Bearer {access_token}",
          "x-api-key": API_KEY,
          "Content-Type": "application/json",
          "Content-Encoding": "gzip",
      },
      data=compressed,
  )
  result = review_res.json()  # requests automatically decompresses the gzip response
  ```

  ```php PHP theme={null}
  <?php
  // Step 1 — obtain access token
  $credentials = base64_encode("$CLIENT_ID:$CLIENT_SECRET");

  $ch = curl_init($TOKEN_URL);
  curl_setopt_array($ch, [
      CURLOPT_POST           => true,
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_HTTPHEADER     => [
          "Authorization: Basic $credentials",
      ],
  ]);
  $tokenData    = json_decode(curl_exec($ch), true);
  curl_close($ch);
  $accessToken  = $tokenData['access_token'];

  // Step 2 — gzip-compress the JSON body
  // gzencode() produces a valid gzip stream; Content-Encoding: gzip tells the gateway what to expect
  $compressed = gzencode(json_encode($billPayload));

  // Step 3 — submit bill for review
  $ch = curl_init("$API_ENDPOINT/v1/review");
  curl_setopt_array($ch, [
      CURLOPT_POST           => true,
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_ENCODING       => 'gzip',   // sends Accept-Encoding: gzip and auto-decompresses the response
      CURLOPT_HTTPHEADER     => [
          "Authorization: Bearer $accessToken",
          "x-api-key: $API_KEY",
          "Content-Type: application/json",
          "Content-Encoding: gzip",
      ],
      CURLOPT_POSTFIELDS => $compressed,
  ]);
  $result = json_decode(curl_exec($ch), true);
  curl_close($ch);
  ```

  ```ruby Ruby theme={null}
  require 'net/http'
  require 'uri'
  require 'json'
  require 'base64'
  require 'zlib'
  require 'stringio'

  # Step 1 — obtain access token
  token_uri = URI(TOKEN_URL)
  token_req = Net::HTTP::Post.new(token_uri)
  token_req['Authorization'] = "Basic #{Base64.strict_encode64("#{CLIENT_ID}:#{CLIENT_SECRET}")}"

  token_res = Net::HTTP.start(token_uri.host, token_uri.port, use_ssl: token_uri.scheme == 'https') do |http|
    http.request(token_req)
  end
  access_token = JSON.parse(token_res.body)['access_token']

  # Step 2 — gzip-compress the JSON body
  # Zlib.gzip produces a standard gzip stream; Content-Encoding: gzip tells the gateway what to expect
  compressed = Zlib.gzip(bill_payload.to_json)

  # Step 3 — submit bill for review
  review_uri = URI("#{API_ENDPOINT}/v1/review")
  review_req = Net::HTTP::Post.new(review_uri)
  review_req['Authorization']    = "Bearer #{access_token}"
  review_req['x-api-key']        = API_KEY
  review_req['Content-Type']     = 'application/json'
  review_req['Content-Encoding'] = 'gzip'
  review_req['Accept-Encoding']  = 'gzip'
  review_req.body = compressed

  review_res = Net::HTTP.start(review_uri.host, review_uri.port, use_ssl: review_uri.scheme == 'https') do |http|
    http.request(review_req)
  end

  # Decompress gzip response body if the server returned one
  body = if review_res['content-encoding'] == 'gzip'
    Zlib::GzipReader.new(StringIO.new(review_res.body)).read
  else
    review_res.body
  end
  result = JSON.parse(body)
  ```

  ```csharp C# theme={null}
  using System.IO.Compression;
  using System.Net;
  using System.Net.Http.Headers;
  using System.Text;
  using System.Text.Json;

  // Step 1 — obtain access token
  var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{CLIENT_ID}:{CLIENT_SECRET}"));

  // Configure HttpClient to automatically decompress gzip responses
  using var handler = new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate };
  using var http = new HttpClient(handler);
  var tokenRequest = new HttpRequestMessage(HttpMethod.Post, TOKEN_URL);
  tokenRequest.Headers.Authorization = new AuthenticationHeaderValue("Basic", credentials);

  var tokenResponse = await http.SendAsync(tokenRequest);
  tokenResponse.EnsureSuccessStatusCode();

  using var tokenDoc = JsonDocument.Parse(await tokenResponse.Content.ReadAsStringAsync());
  var accessToken = tokenDoc.RootElement.GetProperty("access_token").GetString();

  // Step 2 — gzip-compress the JSON body
  // The API gateway forwards Content-Type and Content-Encoding unchanged
  var jsonBytes = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(billPayload));
  using var ms = new MemoryStream();
  using (var gz = new GZipStream(ms, CompressionLevel.Optimal, leaveOpen: true))
      await gz.WriteAsync(jsonBytes);
  var compressed = ms.ToArray();

  // Step 3 — submit bill for review
  var reviewRequest = new HttpRequestMessage(HttpMethod.Post, $"{API_ENDPOINT}/v1/review");
  reviewRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
  reviewRequest.Headers.Add("x-api-key", API_KEY);
  var content = new ByteArrayContent(compressed);
  content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
  content.Headers.ContentEncoding.Add("gzip");
  reviewRequest.Content = content;

  var reviewResponse = await http.SendAsync(reviewRequest);
  reviewResponse.EnsureSuccessStatusCode();

  var result = JsonDocument.Parse(await reviewResponse.Content.ReadAsStringAsync());
  ```
</CodeGroup>
