{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-pages/api/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["admonition","code-group"]},"type":"markdown"},"seo":{"title":"Your first API call","description":"Healthcare APIs and embeddable Elements for patient messaging, appointment booking and clinical record access. Integrated with EMIS Web and TPP SystmOne.","siteUrl":"https://developer.herohealth.net","lang":"en-GB","meta":[{"name":"og:type","content":"website"},{"name":"og:image","content":"https://developer.herohealth.net/images/logo.png"},{"name":"og:site_name","content":"Hero Health Developer Portal"},{"name":"twitter:card","content":"summary"},{"name":"twitter:image","content":"https://developer.herohealth.net/images/logo.png"}],"llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"your-first-api-call","__idx":0},"children":["Your first API call"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This guide walks you through making your first successful API call — registering a patient via NHS PDS (Personal Demographics Service). PDS tracing is at the heart of Hero's patient communication and booking flows: it ensures you're working with the most up-to-date contact details for a patient before sending a message or generating a booking link."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"prerequisites","__idx":1},"children":["Prerequisites"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Before you begin:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["You have joined the ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"https://www.herohealthsoftware.net/partner-program/get-started"},"children":["Hero Partner Programme"]}," and received your API key and practice group ID"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["You have read the ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/pages/api/authentication"},"children":["Authentication guide"]}]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-1-store-your-credentials","__idx":2},"children":["Step 1: Store your credentials"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Store your API key and practice group ID in environment variables. Never hard-code credentials in source files."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"# .env\nHERO_API_KEY=your_staging_or_production_key_here\nHERO_PRACTICE_GROUP_ID=your_practice_group_id_here\n","lang":"bash"},"children":[]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"Start on staging"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use your staging API key and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["https://api.staging.htech.app"]}," as the base URL while building and testing your integration. Switch to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["https://api.herohealth.net"]}," and your production key when you go live."]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-2-register-a-patient-via-pds","__idx":3},"children":["Step 2: Register a patient via PDS"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST /v1/patients/register_pds"]}," traces a patient against the NHS Spine using their NHS number and date of birth. Hero returns a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["patient_id"]}," you can use in subsequent messaging and booking calls."]},{"$$mdtype":"Tag","name":"CodeGroup","attributes":{"mode":"tabs"},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","data-title":"curl","header":{"title":"curl","controls":{"copy":{}}},"source":"curl -X POST \"https://api.staging.htech.app/v1/patients/register_pds\" \\\n  -H \"x-api-key: YOUR_API_KEY\" \\\n  -H \"x-practice-group-id: YOUR_PRACTICE_GROUP_ID\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"nhs_number\": \"123 456 7891\",\n    \"dob\": \"1992-01-01\"\n  }'\n","lang":"bash"},"children":[]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"js","data-title":"Node.js","header":{"title":"Node.js","controls":{"copy":{}}},"source":"const response = await fetch('https://api.staging.htech.app/v1/patients/register_pds', {\n  method: 'POST',\n  headers: {\n    'x-api-key': process.env.HERO_API_KEY,\n    'x-practice-group-id': process.env.HERO_PRACTICE_GROUP_ID,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    nhs_number: '123 456 7891',\n    dob: '1992-01-01',\n  }),\n});\n\nif (!response.ok) {\n  throw new Error(`Request failed: ${response.status}`);\n}\n\nconst data = await response.json();\nconsole.log(data);\n","lang":"js"},"children":[]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ruby","data-title":"Ruby","header":{"title":"Ruby","controls":{"copy":{}}},"source":"require 'net/http'\nrequire 'json'\n\nuri = URI('https://api.staging.htech.app/v1/patients/register_pds')\nhttp = Net::HTTP.new(uri.host, uri.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(uri)\nrequest['x-api-key'] = ENV['HERO_API_KEY']\nrequest['x-practice-group-id'] = ENV['HERO_PRACTICE_GROUP_ID']\nrequest['Content-Type'] = 'application/json'\nrequest.body = JSON.generate({ nhs_number: '123 456 7891', dob: '1992-01-01' })\n\nresponse = http.request(request)\ndata = JSON.parse(response.body)\nputs data\n","lang":"ruby"},"children":[]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-3-understand-the-response","__idx":4},"children":["Step 3: Understand the response"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["There are two possible success responses depending on whether the patient needs to verify their identity."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"patient-registered-successfully","__idx":5},"children":["Patient registered successfully"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"patient_id\": \"98765\"\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Store the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["patient_id"]}," — you'll pass it to subsequent API calls such as generating a booking link or sending a message."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"patient-identity-verification-required","__idx":6},"children":["Patient identity verification required"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"message\": \"Patient must verify their identity before proceeding\",\n  \"login_url\": \"https://patient.herohealth.net/verify/abc123\"\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This occurs when Hero cannot fully confirm the patient's identity from PDS alone. Direct the patient to the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["login_url"]}," to complete verification before retrying."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"handling-errors","__idx":7},"children":["Handling errors"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Status"},"children":["Status"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Cause"},"children":["Cause"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Fix"},"children":["Fix"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["400 Bad Request"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Missing or invalid ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["nhs_number"]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["dob"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Check the request body matches the expected format"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["401 Unauthorized"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Missing or invalid ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["x-api-key"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Verify your key and that you're pointing at the right environment"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["403 Forbidden"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Key does not have access to this practice"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Check your ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["x-practice-group-id"]}," matches your key's configured practice"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["404 Not Found"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["No patient found on PDS for the given NHS number and DOB"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Confirm the details are correct and the patient is registered with NHS"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["429 Too Many Requests"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Rate limit exceeded"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Retry with exponential backoff using the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Retry-After"]}," header"]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"retry-with-backoff","__idx":8},"children":["Retry with backoff"]},{"$$mdtype":"Tag","name":"CodeGroup","attributes":{"mode":"tabs"},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"js","data-title":"Node.js","header":{"title":"Node.js","controls":{"copy":{}}},"source":"async function postWithRetry(url, options, retries = 3) {\n  const response = await fetch(url, options);\n\n  if (response.status === 429 && retries > 0) {\n    const retryAfter = parseInt(response.headers.get('Retry-After') || '60', 10);\n    await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));\n    return postWithRetry(url, options, retries - 1);\n  }\n\n  if (!response.ok) {\n    throw new Error(`Request failed: ${response.status}`);\n  }\n\n  return response.json();\n}\n","lang":"js"},"children":[]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ruby","data-title":"Ruby","header":{"title":"Ruby","controls":{"copy":{}}},"source":"def post_with_retry(uri, request, retries: 3)\n  http = Net::HTTP.new(uri.host, uri.port)\n  http.use_ssl = true\n  response = http.request(request)\n\n  if response.code == '429' && retries > 0\n    retry_after = (response['Retry-After'] || '60').to_i\n    sleep(retry_after)\n    return post_with_retry(uri, request, retries: retries - 1)\n  end\n\n  raise \"Request failed: #{response.code}\" unless response.is_a?(Net::HTTPSuccess)\n  JSON.parse(response.body)\nend\n","lang":"ruby"},"children":[]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"next-steps","__idx":9},"children":["Next steps"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["With a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["patient_id"]}," in hand, you can now:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"/pages/api/booking-links/overview"},"children":["Generate a booking link"]}," — invite the patient to book an appointment"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"/pages/api/messaging/overview"},"children":["Send a message"]}," — send the patient a communication"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"/pages/api/get-started/basic-concepts"},"children":["Basic concepts"]}," — understand Hero's full data model"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"a","attributes":{"href":"/apis/public-api/openapi"},"children":["API Reference"]}," — explore all available endpoints"]}]}]},"headings":[{"value":"Your first API call","id":"your-first-api-call","depth":1},{"value":"Prerequisites","id":"prerequisites","depth":2},{"value":"Step 1: Store your credentials","id":"step-1-store-your-credentials","depth":2},{"value":"Step 2: Register a patient via PDS","id":"step-2-register-a-patient-via-pds","depth":2},{"value":"Step 3: Understand the response","id":"step-3-understand-the-response","depth":2},{"value":"Patient registered successfully","id":"patient-registered-successfully","depth":3},{"value":"Patient identity verification required","id":"patient-identity-verification-required","depth":3},{"value":"Handling errors","id":"handling-errors","depth":2},{"value":"Retry with backoff","id":"retry-with-backoff","depth":3},{"value":"Next steps","id":"next-steps","depth":2}],"frontmatter":{"title":"Your First API Call","description":"Make your first Hero Health API call — register a patient via NHS PDS lookup using your API key and practice group ID.","seo":{"title":"Your first API call"}},"lastModified":"2026-04-08T14:06:15.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/pages/api/get-started/your-first-api-call","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}