> For the complete documentation index, see [llms.txt](https://docs.medicare.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.medicare.healthsherpa.com/api-reference/version-2-oauth/authentication.md).

# Authentication

The HealthSherpa for Medicare Partner API v2 uses **OAuth 2.0** **Authorization Code** flow for authentication.

**Production**

<table><thead><tr><th width="109.37890625">Endpoint</th><th width="131.421875">URL</th><th width="559.421875"></th></tr></thead><tbody><tr><td>Production</td><td>Authorization:</td><td><code>https://medicare.healthsherpa.com/oauth/authorize</code></td></tr><tr><td> </td><td>Token: </td><td><code>https://medicare.healthsherpa.com/oauth/token</code></td></tr><tr><td>Staging</td><td>Authorization:</td><td><code>https://medicare-staging.healthsherpa.com/oauth/authorize</code></td></tr><tr><td></td><td>Token: </td><td><code>https://medicare-staging.healthsherpa.com/oauth/token</code></td></tr></tbody></table>

### 1. Redirect User to Authorization Endpoint

Direct the user to:

```
https://medicare.healthsherpa.com/oauth/authorize?
client_id=YOUR_CLIENT_ID&
redirect_uri=YOUR_REDIRECT_URI&
response_type=code&
scope=partner_api_v2
```

**Parameters:**

* `client_id` (required): Your application's Client ID
* `redirect_uri` (required): Must match the URIs registered with HealthSherpa
* `response_type` (required): Always `code`
* `scope` (required): `partner_api_v2` - grants access to the Partner API v2

### **2. User Authorizes Your Application**

The user will see a consent screen asking to authorize your application. Upon approval, they are redirected to your `redirect_uri` with an authorization code:

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

### **3. Exchange Authorization Code for Access Token**

Your server exchanges the authorization code for an access token:

```
curl -X POST https://medicare.healthsherpa.com/oauth/token
-H "Content-Type: application/x-www-form-urlencoded"
-d "grant_type=authorization_code"
-d "code=AUTH_CODE"
-d "client_id=YOUR_CLIENT_ID"
-d "client_secret=YOUR_CLIENT_SECRET"
-d "redirect_uri=YOUR_REDIRECT_URI"
```

**Response**:

```
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "def50200b7a9c3e4f1d2a6b8c9e0f123456789abcdef...",
  "scope": "partner_api_v2"
}
```

**Parameters**:

* `access_token`: Use this token to make API requests
* `token_type`: Always Bearer
* `expires_in`: Token lifetime in seconds, applies to the access token
* `refresh_token`: Use this token to obtain a new access token
* `scope`: Granted permissions, always "partner\_api\_v2"

### **4. Use the Access Token**

Include the access token in the Authorization header of your API requests:

{% code overflow="wrap" %}

```bash
curl https://api.medicare.healthsherpa.com/v2/contacts \
    -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"contact": {"external_id": "CRM123", "first_name": "John", "last_name": "Doe"}}'
```

{% endcode %}

### 5. Refresh Tokens

When your access token expires, use the refresh token to get a new one :

```
curl -X POST https://medicare.healthsherpa.com/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "refresh_token=YOUR_REFRESH_TOKEN" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET"
```

**Response:**

```
{
  "access_token": "NEW_ACCESS_TOKEN",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "NEW_REFRESH_TOKEN",
  "scope": "partner_api_v2"
}
```

Refresh tokens are rotated: when refreshing, store the newly returned `refresh_token` and discard the previous one.

***

### Troubleshooting

#### Invalid or Expired Token

```
{
  "error": {
    "message": "The access token is invalid.",
    "code": "invalid_token"
  }
}
```

**Response**: 401 Unauthorized

**Solution**: Obtain a new access token by repeating the OAuth flow.

#### Missing Authorization Header

```
{
  "error": {
    "message": "Missing authorization header",
    "code": "missing_authorization"
  }
}
```

**Response**: 401 Unauthorized

**Solution**: Include the Authorization: Bearer YOUR\_ACCESS\_TOKEN header in all requests.

***

### Security Best Practices

* Store Client Secret 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 in frontend code)
