# Authentication The Hero Health Public API uses API key authentication on all requests. Every API key is tied to a specific Hero practice group and partner. Scopes control which endpoints your key can access. ## Getting your API key ### Step 1: Join the Partner Programme Before you can access Hero's APIs, you need to become a verified partner: 1. Fill out our partner onboarding form at our [Get Started page](https://www.herohealthsoftware.net/partner-program/get-started) 2. Review and sign our Partner Agreement (includes SLA and rate limits) 3. Receive access credentials for both staging and production environments ### Step 2: Access developer resources Once approved, you'll receive: - A **staging API key** for development and testing - A **practice group ID** for each practice you're integrating with - Access to our Slack environment for developer support ### Step 3: Secure your credentials Keep your keys secret Never expose API keys in client-side code or commit them to source control. Store keys securely using environment variables or a secrets manager. Use separate keys for staging and production. ## Making authenticated requests All requests require two headers: | Header | Description | | --- | --- | | `x-api-key` | Your Hero Health API key | | `x-practice-group-id` | The ID of the practice you are acting on behalf of | ```bash curl curl -X GET "https://api.herohealth.net/v1/practice-groups" \ -H "x-api-key: YOUR_API_KEY" \ -H "x-practice-group-id: YOUR_PRACTICE_GROUP_ID" ``` ```js Node.js const response = await fetch('https://api.herohealth.net/v1/practice-groups', { method: 'GET', headers: { 'x-api-key': process.env.HERO_API_KEY, 'x-practice-group-id': process.env.HERO_PRACTICE_GROUP_ID, }, }); if (!response.ok) { throw new Error(`Request failed: ${response.status}`); } const data = await response.json(); ``` ```ruby Ruby require 'net/http' require 'json' uri = URI('https://api.herohealth.net/v1/practice-groups') http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(uri) request['x-api-key'] = ENV['HERO_API_KEY'] request['x-practice-group-id'] = ENV['HERO_PRACTICE_GROUP_ID'] response = http.request(request) data = JSON.parse(response.body) ``` ## Environments | Environment | Base URL | Use for | | --- | --- | --- | | **Staging** | `https://api.staging.htech.app` | Development, testing, and integration verification | | **Production** | `https://api.herohealth.net` | Live applications serving real practices | Use test data only in staging — it does not contain real patient information. ## Cross-organisational calls Cross-org access Cross-organisational calls allow you to make API requests on behalf of a different practice group, provided both practices belong to the same Hero-configured network. Hero supports cross-organisational API calls. If the `x-practice-group-id` header you pass does not match the practice group ID configured on your API key, Hero will verify that the target practice exists within a Hero-configured network alongside your key's practice. If such a network exists, the call returns data from the specified practice group. The primary use case is cross-organisational bookings — for example, a practice within a PCN inviting patients to book at a hub site. ### Cross-organisational call flow ```mermaid sequenceDiagram participant Client as Your Server participant Hero as Hero API participant Network as Network Check Client->>Hero: API request
x-api-key: YOUR_KEY
x-practice-group-id: target-practice Hero->>Network: Verify practices share a network alt Network exists Network-->>Hero: Confirmed Hero-->>Client: 200 OK { data from target practice } else No network Network-->>Hero: Denied Hero-->>Client: 403 Forbidden end ``` ## Authentication errors | Status | Error | Cause | | --- | --- | --- | | `401` | `invalid_credentials` | API key is missing, invalid, or expired | | `403` | `insufficient_permissions` | Key does not have the required scope for this endpoint | | `403` | `forbidden` | Cross-org access denied — practices are not in the same network | | `429` | `rate_limit_exceeded` | Too many requests — implement retry with exponential backoff | The API enforces a limit of **300 requests per minute** per API key. Contact [Hero support](mailto:support@herohealth.net) if your integration requires a higher limit. ## Security best practices - Store API keys in environment variables or a secrets manager — never in source code - Use separate keys for staging and production - Request only the minimum scopes your integration needs - All API calls must use HTTPS - Contact Hero support to rotate a compromised key immediately ## Next steps - [Basic concepts](/pages/api/get-started/basic-concepts) — understand Hero's data model - [Your first API call](/pages/api/get-started/your-first-api-call) — make a working API request end-to-end