> For the complete documentation index, see [llms.txt](https://docs.healthsherpa.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.healthsherpa.com/on-exchange-api-documentation/api-reference/intake-form-api/authentication-flow-for-intake-api.md).

# Authentication flow for Intake API

## 1. Set up your OAuth application.

Reach out to HealthSherpa to set up your OAuth application. You will need to provide the following information.

Required:

* Your redirect URI. This is the client endpoint that HealthSherpa redirects the user back to after they authorize their account, carrying the temporary authorization code.

Optional:

* Custom access token time to live. This controls how long the access token is valid. If you do not provide this value, we will default to two hours.

Once you provide the above, we will set up an OAuth application for you. We will provide the following values.

* Your OAuth application ID.
* Your OAuth application secret. This must be kept confidential.

## 2. Redirect the user to the authorization endpoint.

Direct the user to an authorization link. It should have the following format. Please see the GET authorize page for more details.

{% code overflow="wrap" %}

```bash
https://healthsherpa.com/oauth/authorize?client_id=YOUR_OAUTH_APPLICATION_ID&redirect_uri=YOUR_REDIRECT_URI&response_type=code&scope=intake_form_api
```

{% endcode %}

## 3. User authorizes your application.

The user will see a consent screen asking them to authorize your application. When they click the "Approve" button, they will be redirected to your redirect URI. The redirect will include an authorization code and a state value, if you set one up.

```bash
YOUR_REDIRECT_URI?code=AUTH_CODE&state=STATE_VALUE
```

Note: The authorization flow is intentionally split into two stages for security reasons. The authorization code in step 3 travels through the agent's browser via a URL redirect, which is not a secure channel. It passes through browser history, server logs, and potentially referrer headers. For this reason, the code is short-lived and cannot be used to make API calls on its own. To convert it into a usable access token, your backend must make a server-to-server POST in step 4 that combines the code with your confidential client\_secret. That exchange happens entirely on your server and never touches the browser.

{% hint style="info" %}
This is a one-time authorization, as long as you persist valid refresh tokens (see below).&#x20;
{% endhint %}

## 4. Issue an access token.

Take the authorization code from step 3 and issue an access token. Please see the POST token page for more details.

```bash
curl -L \
  --request POST \
  --url 'https://healthsherpa.com/oauth/token' \
  --header 'Content-Type: application/json' \
  --data '{
    "grant_type": "authorization_code",
    "client_id": "YOUR_OAUTH_APPLICATION_ID",
    "client_secret": "YOUR_OAUTH_APPLICATION_SECRET",
    "redirect_uri": "YOUR_REDIRECT_URI",
    "code": "AUTHORIZATION_CODE"
  }'
```

## 5. Use the access token.

Include the access token in the Authorization header of your API requests. Please see the Intake Form API page for more details.

```bash
curl -sS -X POST "https://staging.healthsherpa.com/external/intake_forms" \
  -H "Authorization: Bearer YOUR_OAUTH2_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "first_name": "John",
    "last_name": "Doe",
    "email": "john.doe@email.com",
    "phone_number": "5551234567",
    "someone_has_employer_coverage": false,
    "address": "123 Main St",
    "city": "Exampleville",
    "state": "AZ",
    "zip": "85001",
    "projected_income_members": [
      { "name": "Jane Doe", "employer": "Example Company", "amount": 42000.0 }
    ],
    "tax_household_members": [
      { "name": "John Doe", "date_of_birth": "1980-01-01", "sex": "male", "relationship": "primary", "uses_tobacco": false }
    ]
  }'  | jq .
```

Response:&#x20;

```bash
{
  "id": 85,
  "shopping_url": "https://staging.healthsherpa.com/public/shop?_agent_id=TestAgent2&household_income=42000&household_size=1&intake_form_id=85&people%5Bprimary%5D%5Bage%5D=46&people%5Bprimary%5D%5Bgender%5D=male&people%5Bprimary%5D%5Buses_tobacco%5D=false&skip=true&user_type=agent&zip_code=85001",
  "client_apply_url": "https://staging.healthsherpa.com/public/apply?_agent_id=TestAgent2&intake_form_id=85&state=AZ&user_type=agent",
  "user_uploaded_note_content": null,
  "email": "john.doe@email.com",
  "external_id": null,
  "first_name": "John",
  "last_name": "Doe",
  "phone_number": "5551234567",
  "someone_has_employer_coverage": false,
  "address": "123 Main St",
  "address_2": null,
  "city": "Exampleville",
  "state": "AZ",
  "zip": "85001",
  "projected_income_members": [
    {
      "name": "Jane Doe",
      "employer": "Example Company",
      "amount": 42000.0
    }
  ],
  "tax_household_members": [
    {
      "name": "John Doe",
      "date_of_birth": "1980-01-01",
      "sex": "male",
      "relationship": "primary",
      "uses_tobacco": false
    }
  ]
```

Updating an Intake form:&#x20;

```bash
curl -L \
  --request PATCH \
  --url 'https://healthsherpa.com/external/intake_forms/{intake_form_id}' \
  --header 'Authorization: Bearer YOUR_OAUTH2_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
    "user_uploaded_note_content": "Sample intake notes here."
  }'
```

**The intake form response includes two prefilled deeplink URLs.**

`shopping_url` links to the HealthSherpa plan quoter, allowing the agent or client to select a plan before starting the application.

`client_apply_url` links directly to the Start Application page.&#x20;

The key difference is where the agent selects the plan on HealthSherpa.&#x20;

`shopping_url` will prompt the agent to select the plan before starting the application.&#x20;

`client_apply_url` has the agent start the application and complete it through eligibility determination, then select the plan just before application submission.&#x20;

## 6. Refresh tokens.

When the user's access token expires, you can use the refresh token to get a new one. Refresh tokens do not expire.&#x20;

Each successful refresh call invalidates the refresh token you submitted. The response returns a new access token and a new refresh token. Both values must be persisted immediately, atomically, and in place of the previous tokens.

⚠️ **Important:** Refresh tokens are single-use. If you fail to save the new refresh token from the response, your integration will lose all access to the agent's account, and the agent will need to re-authorize from scratch (steps 2 through 4). Persist the new refresh token before retrying any failed API call.

```bash
curl -L \
  --request POST \
  --url 'https://healthsherpa.com/oauth/token' \
  --header 'Content-Type: application/json' \
  --data '{
    "grant_type": "refresh_token",
    "client_id": "YOUR_OAUTH_APPLICATION_ID",
    "client_secret": "YOUR_OAUTH_APPLICATION_SECRET",
    "refresh_token": "YOUR_REFRESH_TOKEN",
    "redirect_uri": "YOUR_REDIRECT_URI"
  }'
```

## Revoking Tokens

Revoking a token immediately invalidates the agent's access. Any subsequent API call using a token derived from that authorization will return a 401 error. The agent must complete the full authorization flow again (steps 2 through 4) to restore access. Revocation cannot be undone.

## Best practices:

* Store client secrets securely. Use environment variables or secrets management.
* Use HTTPS for all requests.
* Validate redirect URIs.
* Rotate access tokens regularly.
* Use short-lived access tokens.
* Store tokens securely on your backend. Never store tokens in frontend code.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.healthsherpa.com/on-exchange-api-documentation/api-reference/intake-form-api/authentication-flow-for-intake-api.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
