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

# API Integration

> Learn how to integrate Hum into your application using our API

# Building with the Hum API

The Hum API provides endpoints for discovering available internet service providers, plans, and pricing at addresses in the United States. With a single API call, you can retrieve available internet options for an address and immediately display them to your users.

The partner API provides availability lookup and reporting. Residents place orders through the Hum widget checkout; the partner API does not provide an order-placement endpoint.

<Info>
  The Hum API returns provider data immediately in the session creation response - no polling or additional requests required.
</Info>

## Integration Overview

Integrating with Hum is a simple three-step process:

1. **Authenticate** with your API key
2. **Create a session** with the service address
3. **Display results** from the immediate response

## Quick Start Guide

Start in Sandbox with the examples below. To go live, switch the base URL to `https://api.letshum.com` and use your Production key; see [Environments and API Keys](/environments).

<Steps>
  <Step title="Get Your API Key">
    See [Environments and API Keys](/environments) to request an API key and choose the matching environment.
  </Step>

  <Step title="Create a Session and Get Immediate Results">
    Make a POST request to create a session with the service address. The API returns all available providers immediately in the response.

    ```bash cURL theme={null}
    curl -X POST https://api-sandbox.letshum.com/sessions \
      -H "Authorization: Bearer hum_sandbox_XXXXXXXXXXXXXXXXXXXXXXXXXX" \
      -H "Content-Type: application/json" \
      -d '{
        "street1": "29090 Tiffany Drive E",
        "street2": "Apt 4B",
        "zip": "48034"
      }'
    ```

    ```json Success Response theme={null}
    {
      "message": "Session created successfully.",
      "request_status": "ok",
      "data": [
        {
          "provider_id": "130317",
          "provider_name": "Xfinity",
          "provider_icon": null,
          "provider_logo": "https://cdn.example.com/providers/xfinity-logo.png",
          "provider_promo": {},
          "button_label": "xfinity.com",
          "telephone": "+18332981431",
          "url": "https://affiliate.example.com/xfinity?session=SESSION_TOKEN_PLACEHOLDER",
          "url_promo": {},
          "min_plan_price": {
            "currency": "USD",
            "amount_cents": 4000
          },
          "offerings": [
            {
              "technology": "Cable",
              "max_download_speed": 1200,
              "max_upload_speed": 35
            }
          ],
          "product_catalog": [
            {
              "category": "internet",
              "category_name": "Internet Service",
              "category_description": "High-speed internet access plans",
              "products": [
                {
                  "id": "003aa129-5b35-443e-8ea6-c3a33977b5ab",
                  "sku": "130317-INT-CBL-02",
                  "name": "300 Mbps",
                  "category": "internet",
                  "category_name": "Internet Service",
                  "technology": "cable",
                  "position": 2,
                  "description": "Great for everyday working, streaming, and learning. Price guaranteed for 60 months. No contract required.",
                  "select_type": "radio",
                  "download_speed": "300",
                  "upload_speed": "100",
                  "data_limit": "Unlimited",
                  "channel_count": 0,
                  "streaming_apps": [],
                  "is_required_to_checkout": true,
                  "is_contract_required": false,
                  "is_modem_router_included": true,
                  "is_bundle_qualifier": false,
                  "bundle_discounts": {},
                  "is_local_checkout": true,
                  "required_with_plans": [],
                  "included_with_plans": [],
                  "initial_term_discount_months": 60,
                  "second_term_discount_months": null,
                  "only_available_with_plans": [],
                  "hum_rank": 69,
                  "pricing": {
                    "extra_data_fee": {
                      "amount_cents": 0,
                      "currency": "USD"
                    },
                    "professional_installation_fee": {
                      "amount_cents": 5000,
                      "currency": "USD"
                    },
                    "self_installation_fee": {
                      "amount_cents": 0,
                      "currency": "USD"
                    },
                    "activation_fee": {
                      "amount_cents": 0,
                      "currency": "USD"
                    },
                    "initial_term_discount": {
                      "amount_cents": 1500,
                      "currency": "USD"
                    },
                    "second_term_discount": {
                      "amount_cents": 0,
                      "currency": "USD"
                    },
                    "third_term_discount": {
                      "amount_cents": 0,
                      "currency": "USD"
                    },
                    "autopay_discount": {
                      "amount_cents": 0,
                      "currency": "USD"
                    },
                    "paperless_billing_discount": {
                      "amount_cents": 0,
                      "currency": "USD"
                    },
                    "combined_autopay_paperless_discount": {
                      "amount_cents": 1000,
                      "currency": "USD"
                    },
                    "net_monthly_price": {
                      "amount_cents": 5500,
                      "currency": "USD"
                    },
                    "gross_monthly_fee": {
                      "amount_cents": 8000,
                      "currency": "USD"
                    }
                  },
                  "max_quantity": 1,
                  "product_promo": {},
                  "info": "5-year price lock guarantee"
                }
              ]
            }
          ]
        }
      ],
      "meta": {
        "session_token": "SESSION_TOKEN_PLACEHOLDER",
        "session_status": "open",
        "session_params": {
          "street1": "29090 Tiffany Dr E",
          "street2": "Apt 4B",
          "city": "Southfield",
          "state": "MI",
          "zip": "48034",
          "latitude": "42.50189",
          "longitude": "-83.29528",
          "campaign_id": null
        },
        "service_address": "29090 Tiffany Dr E Apt 4B, Southfield, MI 48034-4540",
        "mdu": true,
        "agent_status": {
          "geocoding": "matched",
          "internet": "matched",
          "checkout": "pending"
        },
        "created_at": "2026-07-13T12:26:15.618-04:00",
        "updated_at": "2026-07-13T12:26:15.618-04:00",
        "responded_at": "2026-07-13T16:26:16.278Z",
        "hum_data_set": "26011015"
      }
    }
    ```

    <Check>
      Verify the response includes `request_status: "ok"` and provider data in the `data` array.
    </Check>
  </Step>

  <Step title="Display Available Internet Plans">
    The session creation response includes all available providers and their offerings. You can immediately display this information to your users:

    * Provider name and contact details
    * Available plans with speeds and pricing
    * Direct links to provider signup pages
    * Technology types (DSL, Cable, Fiber, etc.)

    <Tip>
      Process the provider data immediately from the session creation response - no additional API calls needed.
    </Tip>
  </Step>
</Steps>

## Optional: Retrieve Session Details Later

If you need to retrieve session information later, you can use the session token:

```bash cURL theme={null}
curl -X GET https://api-sandbox.letshum.com/sessions/YOUR_SESSION_TOKEN \
  -H "Authorization: Bearer hum_sandbox_XXXXXXXXXXXXXXXXXXXXXXXXXX"
```

This endpoint returns session details and normalized address metadata. Its `data` object contains only the session token:

```json Session Details Response theme={null}
{
  "message": "Session agents have successfully matched the service address. Please proceed.",
  "request_status": "ok",
  "data": {
    "session_token": "SESSION_TOKEN_PLACEHOLDER"
  },
  "meta": {
    "session_token": "SESSION_TOKEN_PLACEHOLDER",
    "session_status": "open",
    "session_params": {
      "street1": "29090 Tiffany Dr E",
      "street2": "Apt 4B",
      "city": "Southfield",
      "state": "MI",
      "zip": "48034",
      "latitude": "42.50189",
      "longitude": "-83.29528",
      "campaign_id": null
    },
    "service_address": "29090 Tiffany Dr E Apt 4B, Southfield, MI 48034-4540",
    "mdu": true,
    "agent_status": {
      "geocoding": "matched",
      "internet": "matched",
      "checkout": "pending"
    },
    "created_at": "2026-07-13T12:26:15.618-04:00",
    "updated_at": "2026-07-13T12:26:15.618-04:00",
    "responded_at": "2026-07-13T16:26:16.900Z",
    "hum_data_set": "26011015"
  }
}
```

While the session is open, retrieve its provider offerings again with `GET /sessions/{token}/services/internet`. See [Get Internet Service Availability](/api-reference/service-availability/get-internet-service-availability) in the API Reference.

## Session Lifecycle

Sessions stay open until you close them with `DELETE /sessions/{token}`. Close a session when its lookup is finished; see [Close Session](/api-reference/sessions/close-session).

## Authentication

All API requests require authentication using your API key. Include it in the Authorization header:

```bash theme={null}
Authorization: Bearer YOUR_API_KEY
```

Use authenticated `GET /ping` as the safest first call before creating a session. It verifies that the selected environment accepts your key; see [Environments and API Keys](/environments#verify-your-key).

## Error Handling

The API uses HTTP status codes to indicate success or failure. Standard validation, authentication, and session errors return this format:

```json Error Response Format theme={null}
{
  "message": "Invalid session token.",
  "request_status": "warning"
}
```

Validation responses may also include an `errors` object with field-specific details.

<Warning>
  Use the HTTP status code to determine whether a request succeeded. The `request_status` field is informational.
</Warning>

Successful session metadata identifies the Hum data set with a numeric string such as `"26011015"`. Infrastructure responses such as HTTP 415, 429, and 500 use the formats documented in the API Reference.

### Common Error Scenarios

<AccordionGroup>
  <Accordion title="400 Bad Request">
    **Common causes:**

    * Missing session parameters
    * Unpermitted session parameters
    * Invalid session token

    **Resolution:** Verify the request body uses supported session fields and confirm that the session token is correct.
  </Accordion>

  <Accordion title="401 Unauthorized - Authentication Issues">
    **Common causes:**

    * Missing or invalid API key
    * Expired API key
    * Invalid authentication header format

    **Resolution:** Verify your API key is correct and properly formatted in the Authorization header.
  </Accordion>

  <Accordion title="415 Unsupported Media Type">
    **Common causes:**

    * Unsupported or incorrect request content type

    **Resolution:** Send session creation requests with `Content-Type: application/json`.
  </Accordion>

  <Accordion title="422 Unprocessable Entity - Validation Failed">
    **Common causes:**

    * Missing a valid address combination: `street1` + `zip`, `street1` + `city` + `state`, or `street1` + `city` + `zip`
    * Invalid address, state, or ZIP format

    ```json Example theme={null}
    {
      "message": "Session could not be created.",
      "request_status": "warning",
      "errors": {
        "base": [
          "Provide either (street1 and zip), (street1, city, and state), or (street1, city, and zip)"
        ]
      }
    }
    ```

    **Resolution:** Use the `errors` object to correct the address fields before retrying.
  </Accordion>

  <Accordion title="503 Service Unavailable - Address Validation">
    Address validation is temporarily unavailable.

    ```json Response theme={null}
    {
      "address_validation_unavailable": true
    }
    ```

    **Resolution:** Respect the `Retry-After` response header and retry later.
  </Accordion>

  <Accordion title="429 Too Many Requests - Rate Limiting">
    **Common causes:**

    * Rate limit exceeded

    **Resolution:** Wait for the delay specified by the `Retry-After` header before retrying.
  </Accordion>

  <Accordion title="500 Internal Server Error - Server Issues">
    **Common causes:**

    * Unexpected server-side failure

    **Resolution:** Retry the request after a brief delay. Contact support if the issue persists.
  </Accordion>
</AccordionGroup>

For detailed error codes and handling, refer to the [API Reference](/api-reference/sessions/create-new-session) documentation.

## Best Practices

<CardGroup cols={2}>
  <Card title="Address Validation" icon="location-dot">
    Provide accurate address data upfront to ensure the best results. Include complete address details including street number, street name, city, state, and ZIP code.

    <Tip>
      Use address validation services before sending requests to minimize errors and improve match rates.
    </Tip>
  </Card>

  <Card title="Error Handling" icon="triangle-exclamation">
    Implement robust error handling for common scenarios like invalid addresses, no service availability, or API rate limits.

    <Warning>
      Always provide clear feedback to users when errors occur, using the error messages and status codes from the API response.
    </Warning>
  </Card>

  <Card title="Session Management" icon="key">
    Store and manage session tokens appropriately. Each session represents a unique address lookup, and tokens can be used to retrieve session details later.
  </Card>

  <Card title="Performance Optimization" icon="gauge-high">
    Consider caching provider data for frequently requested addresses to improve response times and reduce API calls.

    <Tip>
      Process the immediate provider data returned in the session creation response to display options without delay.
    </Tip>
  </Card>
</CardGroup>

## Example Integration

Here's a complete example showing how to integrate the Hum API in different programming languages:

<CodeGroup>
  ```javascript Node.js theme={null}
  async function findInternetProviders(address) {
    try {
      const response = await fetch('https://api-sandbox.letshum.com/sessions', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${process.env.HUM_API_KEY}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(address)
      });

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      const data = await response.json();
      
      // Providers are immediately available in data.data
      const providers = data.data;
      const sessionToken = data.meta.session_token;
      
      console.log(`Found ${providers.length} providers at ${address.street1}`);
      
      return {
        providers,
        sessionToken,
        serviceAddress: data.meta.service_address
      };
      
    } catch (error) {
      console.error('Error finding providers:', error);
      throw error;
    }
  }

  // Usage
  const address = {
    street1: "1001 Woodward Ave",
    city: "Detroit",
    state: "MI",
    zip: "48226"
  };

  findInternetProviders(address)
    .then(result => {
      result.providers.forEach(provider => {
        console.log(`${provider.provider_name}: Starting at $${provider.min_plan_price.amount_cents / 100}/mo`);
      });
    })
    .catch(error => {
      console.error('Failed to find providers:', error);
    });
  ```

  ```python Python theme={null}
  import requests
  import os
  import json

  def find_internet_providers(address):
      try:
          response = requests.post(
              'https://api-sandbox.letshum.com/sessions',
              headers={
                  'Authorization': f'Bearer {os.getenv("HUM_API_KEY")}',
                  'Content-Type': 'application/json'
              },
              json=address
          )
          
          response.raise_for_status()
          data = response.json()
          
          # Providers are immediately available in data['data']
          providers = data['data']
          session_token = data['meta']['session_token']
          
          print(f"Found {len(providers)} providers at {address['street1']}")
          
          return {
              'providers': providers,
              'session_token': session_token,
              'service_address': data['meta']['service_address']
          }
          
      except requests.exceptions.RequestException as error:
          print(f'Error finding providers: {error}')
          raise

  # Usage
  address = {
      'street1': '1001 Woodward Ave',
      'city': 'Detroit',
      'state': 'MI',
      'zip': '48226'
  }

  try:
      result = find_internet_providers(address)
      for provider in result['providers']:
          price = provider['min_plan_price']['amount_cents'] / 100
          print(f"{provider['provider_name']}: Starting at ${price}/mo")
  except Exception as error:
      print(f'Failed to find providers: {error}')
  ```

  ```php PHP theme={null}
  <?php

  function findInternetProviders($address) {
      $apiKey = $_ENV['HUM_API_KEY'];
      
      $curl = curl_init();
      
      curl_setopt_array($curl, [
          CURLOPT_URL => 'https://api-sandbox.letshum.com/sessions',
          CURLOPT_RETURNTRANSFER => true,
          CURLOPT_POST => true,
          CURLOPT_HTTPHEADER => [
              'Authorization: Bearer ' . $apiKey,
              'Content-Type: application/json'
          ],
          CURLOPT_POSTFIELDS => json_encode($address)
      ]);
      
      $response = curl_exec($curl);
      $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
      curl_close($curl);
      
      if ($httpCode !== 201) {
          throw new Exception("HTTP error! status: $httpCode");
      }
      
      $data = json_decode($response, true);
      
      // Providers are immediately available in data['data']
      $providers = $data['data'];
      $sessionToken = $data['meta']['session_token'];
      
      echo "Found " . count($providers) . " providers at " . $address['street1'] . "\n";
      
      return [
          'providers' => $providers,
          'sessionToken' => $sessionToken,
          'serviceAddress' => $data['meta']['service_address']
      ];
  }

  // Usage
  $address = [
      'street1' => '1001 Woodward Ave',
      'city' => 'Detroit',
      'state' => 'MI',
      'zip' => '48226'
  ];

  try {
      $result = findInternetProviders($address);
      foreach ($result['providers'] as $provider) {
          $price = $provider['min_plan_price']['amount_cents'] / 100;
          echo $provider['provider_name'] . ": Starting at $" . $price . "/mo\n";
      }
  } catch (Exception $error) {
      echo 'Failed to find providers: ' . $error->getMessage() . "\n";
  }

  ?>
  ```
</CodeGroup>

## Next Steps

<CardGroup cols={3}>
  <Card title="API Reference" icon="book" href="/api-reference/sessions/create-new-session">
    Explore detailed endpoint documentation, parameter specifications, and response schemas.
  </Card>

  <Card title="Postman Collection" icon="circle-play" href="/postman">
    Import ready-made requests for Sandbox or Production.
  </Card>

  <Card title="Widget Integration" icon="puzzle-piece" href="/widget-integration/overview">
    Try our no-code widget solution for quick integration without custom development.
  </Card>
</CardGroup>
