Step 1: Sign in and choose an organization

Add MCP server to your AI tool

Allow AI tools and LLMs to interact with the API documentation portal through MCP.

MCP server URL

https://docs.usehearsay.com/mcp

Standard setup for AI tools providing an mcp.json file

mcp.json
{
  "Partner APIs MCP server": {
    "url": "https://docs.usehearsay.com/mcp"
  }
}

Close

First time: register

POST /auth/register creates the user. If that user does not already belong to an organization, it also creates one, with the user as its owner.

  • Required: email, password, name.
  • userType is optional free text; the Hearsay apps send professional or individual.
  • termsAccepted must be true; without it the call returns 400.
  • organizationName names the new organization. If you leave it out, the name comes from the user's name. A name that is already taken returns 400.
  • Optional: phone (a list of numbers) and inviteEmails (colleagues to invite).
  • On success you are already signed in: the response carries an access token, a refresh token, the user's profile and the organization. You do not need to call login straight after.
  • Optional pre-check: POST /auth/check-email-availability tells you whether an email can sign up. It needs no token and allows only 10 calls per minute.

Returning user: log in

POST /auth/login with email and password returns:

  • accessToken: send it as Authorization: Bearer <accessToken>.
  • refreshToken: keep it to get new access tokens.
  • userProfile: includes userOrganizations, the organizations this user belongs to.

Wrong credentials and inactive accounts return 401.

Choose the organization

Each entry of userProfile.userOrganizations has an organization (with its id and name) and a permission (with your role). Take organization.id and send it in the organization header on every later call.

If the user belongs to several organizations, pick by name, or ask a human. Never guess. GET /organization/user/organizations returns the same list at any time.

Keep the session alive

  • When a call returns 401 because the access token expired, call POST /auth/refresh with the refreshToken. You get a new access token; the refresh token stays the same. Then retry the original call once.
  • If the refresh itself fails (404 for an unknown token, 400 for an expired one), log in again.
  • POST /auth/logout ends the current session.

Long-running agents: API tokens

For an unattended agent, a long-lived token is often easier than storing a password. While signed in, call POST /auth/generate-token. There are two kinds:

Kind How to get it What it can do Lifetime
Scoped automation token Send scopes (and optionally label and ttlDays) Only the routes its scopes allow. Every other route returns 403. ttlDays, 1 to 400 days (default about 365)
Full-access token Send no scopes, and no label or ttlDays (those return 400 without scopes) Everything the user can do 5 years

The scopes and the routes each one unlocks:

Scope Routes it unlocks
cases:create POST /case
codes:create POST /case/{caseId}/extraction
exports:create POST /case/{caseId}/export and POST /case/{caseId}/export/{exportId}/rerun


A scoped token cannot list or update cases, list or update extraction codes, or list or download exports. An integration that runs the full workflow in this guide needs either a normal login session (recommended) or a full-access token (see the token rules below). Use scoped tokens for agents that only create things.

Token rules:

  • The token value is shown once, in the generate-token response. Store it in a secret store, never in logs or prompts.
  • GET /auth/tokens lists your scoped tokens (never their values). DELETE /auth/tokens/{id} revokes one, and PATCH /auth/tokens/{id}/scopes changes its scopes; an empty scope list disables the token without deleting it.
  • Full-access tokens are not listed by GET /auth/tokens and have no id, so DELETE /auth/tokens/{id} cannot revoke them. The only way to revoke one is to call POST /auth/logout with that token. If it is lost or leaked, you cannot revoke it yourself; contact Hearsay. Prefer a normal login session for the full workflow, and use a full-access token only if you must.
  • Scoped tokens can be switched off on Hearsay's side. If generate-token returns 403, ask Hearsay to enable them for you.
  • You still send the organization header with an API token.

Log in:

curl -X POST "https://api.usehearsay.com/auth/login" \
  -H "Content-Type: application/json" \
  -d '{"email": "jane.doe@example.com", "password": "..."}'
{
  "data": {
    "accessToken": "eyJhbGciOi...",
    "refreshToken": "b7c1e2f0a9d8...",
    "userProfile": {
      "id": "507f1f77bcf86cd799439011",
      "name": "Jane Doe",
      "userOrganizations": [
        {
          "organization": {
            "id": "507f1f77bcf86cd799439012",
            "name": "Example Law LLP"
          },
          "permission": { "role": "owner" }
        }
      ]
    }
  },
  "statusCode": 200,
  "timestamp": "2026-01-15T10:15:00.000Z"
}

Refresh an expired access token:

curl -X POST "https://api.usehearsay.com/auth/refresh" \
  -H "Content-Type: application/json" \
  -d '{"refreshToken": "'"$REFRESH_TOKEN"'"}'

Create a scoped automation token:

curl -X POST "https://api.usehearsay.com/auth/generate-token" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"label": "Intake sync", "scopes": ["cases:create", "codes:create"], "ttlDays": 90}'