MedTrainer Public API (1.0.0)

The MedTrainer Public API allows external integrations to search and manage core directory resources such as locations, divisions, and practitioners.

This specification describes the available endpoints, request parameters, payloads, authentication requirements, and expected responses for clients integrating with the platform.

Most resource endpoints return FHIR-aligned JSON with content type application/fhir+json. Protected endpoints accept authentication through either the X-API-Key header or Authorization: Bearer <token>.

Getting started

This guide walks you through how to generate an API Key from the platform. This key will allow you to authenticate and interact with the available APIs.

Prerequisites

Before you begin, make sure you have:

A valid account and access to the platform

Proper permissions to generate an API Key (Super Admin / Admin)

Logged into the platform

Step-by-step

1. Log in to the platform

Sign in to the MedTrainer platform using your credentials.

2. Open Organization settings

Once you're in:

On the left-side menu

Click on Organization

3. Expand “Organization Management” and find the “API keys manager”

Inside Organization Settings:

Expand “Organization Management” menu

Here you’ll find all options to configure the organization

Look for “API keys manager” option and click on it

4. Create a new API Key group

In the “API keys manager” page:

Click on “Create API key group”

Fill the following fields:

name

description

Confirm the action by clicking the “Create” button.

5. Activate the API Key “Default”

After generating the API key group:

On the “API Keys Manager” page, you will see the newly created API key group, along with a “Default” API key in an “Inactive” status.

To activate the “Default” API key:

Click on the status to expand the available options.

Once the list is expanded, select the “Active” status

This API key is required and must be available to use the MedTrainer Public APIs
Important: Treat your API Key like a password. Keep it private and secure.

Locations

Public location lookup and mutation endpoints

Search locations

Returns a FHIR Bundle with location resources.

Authorizations:
ApiKeyHeaderBearerAuth
query Parameters
_count
integer >= 1
Default: 20

Number of resources to return. Must be a positive integer.

_page
integer >= 1
Default: 1

1-based page number. Must be a positive integer.

_elements
string
Example: _elements=id,name

Comma-separated field selector.

For location and division searches, the implemented selectors are id, name, and locations (the locations child array is only meaningful for divisions). The default when _elements is omitted: locations default to id,name; divisions default to id,name,locations.

For practitioners, nested selectors are allowed, including values such as telecom.email, address.city, extension.user.status, extension.user.statusReason, extension.user.userType, or extension.provider.npiNumber. The public practitioner response uses extension.user.status and extension.user.statusReason for the visible status state; the legacy employeeCategoryId is not exposed. When _elements is omitted on practitioner search or get-by-id, the full resource as returned by the backing service is emitted.

Whitespace around values is trimmed. Unknown selectors are preserved in pagination links but ignored when each resource is built.

Pagination link.url values are returned as absolute URLs including scheme and host (for example, /api/v1/... resolves against the active server entry).

Responses

Response samples

Content type
application/fhir+json
{
  • "resourceType": "Bundle",
  • "type": "searchset",
  • "total": 3,
  • "link": [
    ],
  • "entry": [
    ]
}

Create a location

Authorizations:
ApiKeyHeaderBearerAuth
Request Body schema: application/json
required
name
required
string [ 1 .. 100 ] characters

Required location name. Cannot be blank or whitespace-only.

locations
Array of strings[ items non-empty ]

Optional list of child location public IDs. Each value cannot be blank or whitespace-only.

Responses

Request samples

Content type
application/json
Example
{
  • "name": "North Campus",
  • "locations": [
    ]
}

Response samples

Content type
application/fhir+json
{
  • "resourceType": "OperationOutcome",
  • "issue": [
    ]
}

Get a location by public ID

Authorizations:
ApiKeyHeaderBearerAuth
path Parameters
publicId
required
string
Example: LOC-001

Public location identifier.

Responses

Response samples

Content type
application/fhir+json
{
  • "resourceType": "Location",
  • "id": "LOC-001",
  • "name": "North Campus"
}

Update a location

Updates a location identified by publicId.

Authorizations:
ApiKeyHeaderBearerAuth
path Parameters
publicId
required
string
Example: LOC-001

Public location identifier.

Request Body schema: application/json
required
name
required
string [ 1 .. 100 ] characters

Required location name. Cannot be blank or whitespace-only.

locations
Array of strings[ items non-empty ]

Optional list of child location public IDs. Each value cannot be blank or whitespace-only.

Responses

Request samples

Content type
application/json
{
  • "name": "North Campus",
  • "locations": [
    ]
}

Response samples

Content type
application/fhir+json
{
  • "resourceType": "OperationOutcome",
  • "issue": [
    ]
}

Update a location with PATCH

Updates a location identified by publicId using the same request body and validation rules as PUT.

Authorizations:
ApiKeyHeaderBearerAuth
path Parameters
publicId
required
string
Example: LOC-001

Public location identifier.

Request Body schema: application/json
required
name
required
string [ 1 .. 100 ] characters

Required location name. Cannot be blank or whitespace-only.

locations
Array of strings[ items non-empty ]

Optional list of child location public IDs. Each value cannot be blank or whitespace-only.

Responses

Request samples

Content type
application/json
{
  • "name": "North Campus",
  • "locations": [
    ]
}

Response samples

Content type
application/fhir+json
{
  • "resourceType": "OperationOutcome",
  • "issue": [
    ]
}

Divisions

Public division lookup and mutation endpoints

Search divisions

Returns a FHIR Bundle with division resources.

Authorizations:
ApiKeyHeaderBearerAuth
query Parameters
_count
integer >= 1
Default: 20

Number of resources to return. Must be a positive integer.

_page
integer >= 1
Default: 1

1-based page number. Must be a positive integer.

_elements
string
Example: _elements=id,name

Comma-separated field selector.

For location and division searches, the implemented selectors are id, name, and locations (the locations child array is only meaningful for divisions). The default when _elements is omitted: locations default to id,name; divisions default to id,name,locations.

For practitioners, nested selectors are allowed, including values such as telecom.email, address.city, extension.user.status, extension.user.statusReason, extension.user.userType, or extension.provider.npiNumber. The public practitioner response uses extension.user.status and extension.user.statusReason for the visible status state; the legacy employeeCategoryId is not exposed. When _elements is omitted on practitioner search or get-by-id, the full resource as returned by the backing service is emitted.

Whitespace around values is trimmed. Unknown selectors are preserved in pagination links but ignored when each resource is built.

Pagination link.url values are returned as absolute URLs including scheme and host (for example, /api/v1/... resolves against the active server entry).

Responses

Response samples

Content type
application/fhir+json
{
  • "resourceType": "Bundle",
  • "type": "searchset",
  • "total": 3,
  • "link": [
    ],
  • "entry": [
    ]
}

Create a division

Creates a division with a non-blank name and at least one linked location public ID.

Authorizations:
ApiKeyHeaderBearerAuth
Request Body schema: application/json
required
name
required
string [ 1 .. 254 ] characters

Required division name. Cannot be blank or whitespace-only.

locations
required
Array of strings non-empty [ items non-empty ]

Required list of location public IDs. At least one value must be provided, and each value cannot be blank or whitespace-only.

Responses

Request samples

Content type
application/json
Example
{
  • "name": "North Division",
  • "locations": [
    ]
}

Response samples

Content type
application/fhir+json
{
  • "resourceType": "OperationOutcome",
  • "issue": [
    ]
}

Get a division by ID

Authorizations:
ApiKeyHeaderBearerAuth
path Parameters
divisionId
required
string
Example: DIV-001

Public division identifier.

Responses

Response samples

Content type
application/fhir+json
{
  • "resourceType": "Division",
  • "id": "DIV-123",
  • "name": "Clinical Division",
  • "locations": [
    ]
}

Update a division

Accepts partial updates. Send at least one of name or locations.

Authorizations:
ApiKeyHeaderBearerAuth
path Parameters
divisionId
required
string
Example: DIV-001

Public division identifier.

Request Body schema: application/json
required
Any of
name
required
string [ 1 .. 254 ] characters

Conditionally required division name. Send name or locations. If name is provided, it cannot be blank or whitespace-only.

locations
Array of strings[ items non-empty ]

Conditionally required list of location public IDs. Send name or locations. Each provided value cannot be blank or whitespace-only. Send an empty array to remove all linked locations.

Responses

Request samples

Content type
application/json
Example
{
  • "name": "Updated Division"
}

Response samples

Content type
application/fhir+json
{
  • "resourceType": "OperationOutcome",
  • "issue": [
    ]
}

Update a division with PATCH

Accepts the same payload as PUT and is routed to the same update handler.

Authorizations:
ApiKeyHeaderBearerAuth
path Parameters
divisionId
required
string
Example: DIV-001

Public division identifier.

Request Body schema: application/json
required
Any of
name
required
string [ 1 .. 254 ] characters

Conditionally required division name. Send name or locations. If name is provided, it cannot be blank or whitespace-only.

locations
Array of strings[ items non-empty ]

Conditionally required list of location public IDs. Send name or locations. Each provided value cannot be blank or whitespace-only. Send an empty array to remove all linked locations.

Responses

Request samples

Content type
application/json
Example
{
  • "name": "Updated Division"
}

Response samples

Content type
application/fhir+json
{
  • "resourceType": "OperationOutcome",
  • "issue": [
    ]
}

Practitioners

Public practitioner lookup, search, and mutation endpoints

Create a practitioner

Creates a practitioner/provider profile for the company resolved from the API key.

Authorizations:
ApiKeyHeaderBearerAuth
Request Body schema: application/json
required
resourceType
string^\s*Practitioner\s*$

Optional resource type discriminator. When present it must equal Practitioner.

id
string non-empty

Optional public practitioner identifier. If present it cannot be blank or whitespace-only.

required
object (PractitionerWriteName)

Practitioner name payload.

given and family are required. Any provided string must contain at least one non-whitespace character.

Every string field below is constrained to letters, numbers, spaces, apostrophes, periods, and hyphens. The character allowlist regex enforced server-side is ^[A-Za-z0-9 .'\-]+$. Length limits enforced by request validation: given/family 255, middle 100, other.given/other.middle/other.family 100, and other.suffix 20.

birthDate
string (MmDdYyyyDateString) ^(0[1-9]|1[0-2])/(0[1-9]|[12][0-9]|3[01])/[0-...

Date string in MM/DD/YYYY format.

The value must represent a real calendar date accepted by server-side validation, not just a string that matches the pattern. For example, 02/31/2026 is rejected.

gender
string [ 1 .. 100 ] characters ^[A-Za-z0-9 .'\-]+$

Only letters, numbers, spaces, apostrophes, periods, and hyphens are allowed. Maximum 100 characters.

required
object (PractitionerWriteTelecom)

Practitioner telecom payload.

email is required. Any provided string must contain at least one non-whitespace character.

object (PractitionerWriteAddress)

Optional address payload used for both address and mailingAddress.

Validation is asymmetric between the two usages. When this schema is referenced as mailingAddress, the server additionally enforces:

  • a character allowlist regex ^[A-Za-z0-9 .'\-]+$ on line[0], line[1], and city
  • maxLength: 100 on county and province

The same regex and length rules are not enforced when the schema is referenced as address. Clients should prefer sending characters that satisfy both rule sets to avoid surprises if the validation is ever unified.

object (PractitionerWriteAddress)

Optional address payload used for both address and mailingAddress.

Validation is asymmetric between the two usages. When this schema is referenced as mailingAddress, the server additionally enforces:

  • a character allowlist regex ^[A-Za-z0-9 .'\-]+$ on line[0], line[1], and city
  • maxLength: 100 on county and province

The same regex and length rules are not enforced when the schema is referenced as address. Clients should prefer sending characters that satisfy both rule sets to avoid surprises if the validation is ever unified.

required
object (PractitionerWriteExtension)

Practitioner extension payload. employment and user are required.

Responses

Request samples

Content type
application/json
{
  • "resourceType": "Practitioner",
  • "id": "EMP-PUB-002",
  • "name": {
    },
  • "birthDate": "01/01/1990",
  • "gender": "male",
  • "telecom": {
    },
  • "address": {
    },
  • "mailingAddress": {
    },
  • "extension": {
    }
}

Response samples

Content type
application/fhir+json
{
  • "resourceType": "OperationOutcome",
  • "issue": [
    ]
}

Search practitioners

Returns a FHIR Bundle of practitioner resources. _elements supports comma-separated selectors and may include nested paths such as telecom.email, address.city, extension.user.status, extension.user.statusReason, extension.user.userType, or extension.provider.npiNumber.

_elements values are normalized by trimming surrounding whitespace. Unknown selectors are preserved in pagination links but ignored when building each practitioner resource.

Authorizations:
ApiKeyHeaderBearerAuth
query Parameters
_count
integer >= 1
Default: 20

Number of resources to return. Must be a positive integer.

_page
integer >= 1
Default: 1

1-based page number. Must be a positive integer.

_elements
string
Example: _elements=id,name

Comma-separated field selector.

For location and division searches, the implemented selectors are id, name, and locations (the locations child array is only meaningful for divisions). The default when _elements is omitted: locations default to id,name; divisions default to id,name,locations.

For practitioners, nested selectors are allowed, including values such as telecom.email, address.city, extension.user.status, extension.user.statusReason, extension.user.userType, or extension.provider.npiNumber. The public practitioner response uses extension.user.status and extension.user.statusReason for the visible status state; the legacy employeeCategoryId is not exposed. When _elements is omitted on practitioner search or get-by-id, the full resource as returned by the backing service is emitted.

Whitespace around values is trimmed. Unknown selectors are preserved in pagination links but ignored when each resource is built.

Pagination link.url values are returned as absolute URLs including scheme and host (for example, /api/v1/... resolves against the active server entry).

Responses

Response samples

Content type
application/fhir+json
Example
{
  • "resourceType": "Bundle",
  • "type": "searchset",
  • "total": 3,
  • "link": [
    ],
  • "entry": [
    ]
}

Get a practitioner by public ID

Returns a single practitioner resource. If _elements is omitted, the full practitioner payload returned by the backing service is emitted. _elements accepts the same nested selector syntax as practitioner search and trims surrounding whitespace before filtering.

Authorizations:
ApiKeyHeaderBearerAuth
path Parameters
publicId
required
string
Example: PRAC-001

Public practitioner identifier.

query Parameters
_elements
string
Example: _elements=id,name

Comma-separated field selector.

For location and division searches, the implemented selectors are id, name, and locations (the locations child array is only meaningful for divisions). The default when _elements is omitted: locations default to id,name; divisions default to id,name,locations.

For practitioners, nested selectors are allowed, including values such as telecom.email, address.city, extension.user.status, extension.user.statusReason, extension.user.userType, or extension.provider.npiNumber. The public practitioner response uses extension.user.status and extension.user.statusReason for the visible status state; the legacy employeeCategoryId is not exposed. When _elements is omitted on practitioner search or get-by-id, the full resource as returned by the backing service is emitted.

Whitespace around values is trimmed. Unknown selectors are preserved in pagination links but ignored when each resource is built.

Pagination link.url values are returned as absolute URLs including scheme and host (for example, /api/v1/... resolves against the active server entry).

Responses

Response samples

Content type
application/fhir+json
Example
{
  • "resourceType": "Practitioner",
  • "name": {
    },
  • "telecom": {
    }
}

Update a practitioner

Updates a practitioner/provider profile identified by publicId.

The request body is a partial update: every top-level field is optional. Only the fields you send are forwarded to the backing service, so omitted fields retain their existing values. Any field that is present is validated with the same format/length/pattern rules as the create payload.

Authorizations:
ApiKeyHeaderBearerAuth
path Parameters
publicId
required
string
Example: PRAC-001

Public practitioner identifier.

Request Body schema: application/json
required
resourceType
string^\s*Practitioner\s*$

Optional resource type discriminator. When present it must equal Practitioner.

object (PractitionerUpdateName)

Practitioner name payload for partial updates. All fields are optional — send only the fields you want to change.

Every string field below is constrained to letters, numbers, spaces, apostrophes, periods, and hyphens. The character allowlist regex enforced server-side is ^[A-Za-z0-9 .'\-]+$. Length limits enforced by request validation: given/family 255, middle 100, other.given/other.middle/other.family 100, and other.suffix 20.

birthDate
string (MmDdYyyyDateString) ^(0[1-9]|1[0-2])/(0[1-9]|[12][0-9]|3[01])/[0-...

Date string in MM/DD/YYYY format.

The value must represent a real calendar date accepted by server-side validation, not just a string that matches the pattern. For example, 02/31/2026 is rejected.

gender
string [ 1 .. 100 ] characters ^[A-Za-z0-9 .'\-]+$

Only letters, numbers, spaces, apostrophes, periods, and hyphens are allowed. Maximum 100 characters.

object (PractitionerUpdateTelecom)

Practitioner telecom payload for partial updates. All fields are optional — send only the fields you want to change. Any provided string must contain at least one non-whitespace character.

object (PractitionerWriteAddress)

Optional address payload used for both address and mailingAddress.

Validation is asymmetric between the two usages. When this schema is referenced as mailingAddress, the server additionally enforces:

  • a character allowlist regex ^[A-Za-z0-9 .'\-]+$ on line[0], line[1], and city
  • maxLength: 100 on county and province

The same regex and length rules are not enforced when the schema is referenced as address. Clients should prefer sending characters that satisfy both rule sets to avoid surprises if the validation is ever unified.

object (PractitionerWriteAddress)

Optional address payload used for both address and mailingAddress.

Validation is asymmetric between the two usages. When this schema is referenced as mailingAddress, the server additionally enforces:

  • a character allowlist regex ^[A-Za-z0-9 .'\-]+$ on line[0], line[1], and city
  • maxLength: 100 on county and province

The same regex and length rules are not enforced when the schema is referenced as address. Clients should prefer sending characters that satisfy both rule sets to avoid surprises if the validation is ever unified.

object (PractitionerUpdateExtension)

Practitioner extension payload for partial updates. All nested objects and their fields are optional — send only the pieces you want to change.

The practitioner user status fields are nested under extension.user.

Responses

Request samples

Content type
application/json
{
  • "resourceType": "Practitioner",
  • "name": {
    },
  • "birthDate": "01/01/1990",
  • "gender": "male",
  • "telecom": {
    },
  • "address": {
    },
  • "mailingAddress": {
    },
  • "extension": {
    }
}

Response samples

Content type
application/fhir+json
{
  • "resourceType": "OperationOutcome",
  • "issue": [
    ]
}

Update a practitioner with PATCH

Accepts the same payload as PUT and is routed to the same update handler. Both verbs behave as partial updates: send only the fields you want to change.

Authorizations:
ApiKeyHeaderBearerAuth
path Parameters
publicId
required
string
Example: PRAC-001

Public practitioner identifier.

Request Body schema: application/json
required
resourceType
string^\s*Practitioner\s*$

Optional resource type discriminator. When present it must equal Practitioner.

object (PractitionerUpdateName)

Practitioner name payload for partial updates. All fields are optional — send only the fields you want to change.

Every string field below is constrained to letters, numbers, spaces, apostrophes, periods, and hyphens. The character allowlist regex enforced server-side is ^[A-Za-z0-9 .'\-]+$. Length limits enforced by request validation: given/family 255, middle 100, other.given/other.middle/other.family 100, and other.suffix 20.

birthDate
string (MmDdYyyyDateString) ^(0[1-9]|1[0-2])/(0[1-9]|[12][0-9]|3[01])/[0-...

Date string in MM/DD/YYYY format.

The value must represent a real calendar date accepted by server-side validation, not just a string that matches the pattern. For example, 02/31/2026 is rejected.

gender
string [ 1 .. 100 ] characters ^[A-Za-z0-9 .'\-]+$

Only letters, numbers, spaces, apostrophes, periods, and hyphens are allowed. Maximum 100 characters.

object (PractitionerUpdateTelecom)

Practitioner telecom payload for partial updates. All fields are optional — send only the fields you want to change. Any provided string must contain at least one non-whitespace character.

object (PractitionerWriteAddress)

Optional address payload used for both address and mailingAddress.

Validation is asymmetric between the two usages. When this schema is referenced as mailingAddress, the server additionally enforces:

  • a character allowlist regex ^[A-Za-z0-9 .'\-]+$ on line[0], line[1], and city
  • maxLength: 100 on county and province

The same regex and length rules are not enforced when the schema is referenced as address. Clients should prefer sending characters that satisfy both rule sets to avoid surprises if the validation is ever unified.

object (PractitionerWriteAddress)

Optional address payload used for both address and mailingAddress.

Validation is asymmetric between the two usages. When this schema is referenced as mailingAddress, the server additionally enforces:

  • a character allowlist regex ^[A-Za-z0-9 .'\-]+$ on line[0], line[1], and city
  • maxLength: 100 on county and province

The same regex and length rules are not enforced when the schema is referenced as address. Clients should prefer sending characters that satisfy both rule sets to avoid surprises if the validation is ever unified.

object (PractitionerUpdateExtension)

Practitioner extension payload for partial updates. All nested objects and their fields are optional — send only the pieces you want to change.

The practitioner user status fields are nested under extension.user.

Responses

Request samples

Content type
application/json
{
  • "resourceType": "Practitioner",
  • "name": {
    },
  • "birthDate": "01/01/1990",
  • "gender": "male",
  • "telecom": {
    },
  • "address": {
    },
  • "mailingAddress": {
    },
  • "extension": {
    }
}

Response samples

Content type
application/fhir+json
{
  • "resourceType": "OperationOutcome",
  • "issue": [
    ]
}