Certifyos Tenant Specialty API

Endpoints for managing tenant-specific specialties.

Operations 6

GET /tenant-specialties List specialties configured for the tenant #
POST /tenant-specialties Add a specialty to the tenant's configuration #
GET /tenant-specialties/by-classification List tenant specialties matching a classification and category #
PUT /tenant-specialties/{id} Replace a tenant specialty's data in full #
GET /tenant-specialties/{id} Fetch a single tenant specialty by its ID #
DELETE /tenant-specialties/{id} Remove a specialty from the tenant's configuration #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/certifyos:certifyos-tenant-specialty-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

certifyos-tenant-specialty-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  description: API for Certify application
  title: Certify API Layer Tenant Specialty API
  version: 1.0.0
servers:
- url: http://localhost:9000
  description: Local Development Server
- url: https://api-service.staging.certifyos.com
  description: Staging Server
- url: https://api-service.internal.certifyos.com
  description: Internal Server
- url: https://api-service.test.certifyos.com
  description: Test Server
- url: https://api-service.demo.certifyos.com
  description: Demo Server
- url: https://api-service.certifyos.com
  description: Production Server
tags:
- name: Tenant Specialty
  description: Endpoints for managing tenant-specific specialties.
paths:
  /tenant-specialties:
    get:
      summary: List specialties configured for the tenant
      description: 'Returns the specialties that have been configured for the tenant identified by the `tenant-id` header.


        **What it does:** Fetches a page of tenant specialty records — each record links a global specialty definition to this tenant and may carry tenant-specific metadata.


        **When to use:** Use this endpoint to display or enumerate specialties active for a tenant. To narrow results to a specific classification taxonomy, use `GET /tenant-specialties/by-classification` instead.


        **How to call it:** Supply the required `tenant-id` header. The `name` query parameter is accepted but is not currently forwarded to the data layer — it has no effect on the returned results (tracked as a known limitation, not fixed by this documentation change). Pagination is not exposed: every call returns a fixed first page of up to 10 records regardless of how many tenant specialties exist for the tenant.


        **What you get back:** A JSON object containing a `data` array of tenant specialty objects and a `totalCount` integer reflecting the full count before pagination. Requires the `READ_TENANT_SPECIALTY` permission.'
      operationId: getTenantSpecialties
      tags:
      - Tenant Specialty
      parameters:
      - description: Filter tenant specialties by name. Accepted but not currently applied by the data layer — has no effect on results.
        example: Cardiology
        in: query
        name: name
        schema:
          type: string
      - description: Tenant identifier that scopes the query.
        required: true
        name: tenant-id
        in: header
        schema:
          type: string
      responses:
        '401':
          description: Unauthorized - the request is missing a valid JWT.
        '403':
          description: Forbidden - the caller lacks the READ_TENANT_SPECIALTY permission for this tenant.
        '500':
          description: Internal Server Error - an unexpected error occurred while retrieving the list.
        '200':
          description: The (fixed first page of the) tenant's specialties, plus the total count before pagination.
          content:
            application/json:
              examples:
                tenantSpecialtyList:
                  value:
                    totalCount: 2
                    data:
                    - displayName: Cardiology
                      description: Diagnosis and treatment of heart conditions.
                      changeReason: Initial tenant onboarding
                    - displayName: Dermatology
                      description: Diagnosis and treatment of skin conditions.
                      changeReason: Initial tenant onboarding
              schema:
                $ref: '#/components/schemas/GetTenantSpecialtiesResponse'
        '400':
          description: Missing or invalid `tenant-id` header.
          content:
            application/json:
              examples:
                missingTenantIdHeader:
                  value:
                    errors:
                    - httpStatus: 400
                      reason: VALIDATION_ERROR
                      title: 'Validation failed for field: getTenantSpecialties.tenantId'
                      detail: must not be null
              schema:
                $ref: '#/components/schemas/ApiError'
      security:
      - jwt: []
    post:
      summary: Add a specialty to the tenant's configuration
      description: 'Creates a new tenant specialty record, associating a global specialty with the tenant identified by the `tenant-id` header.


        **What it does:** Persists a tenant-scoped specialty entry. A tenant specialty is distinct from a global specialty — it represents the tenant''s adoption of a specialty for use in their credentialing workflows.


        **When to use:** Call this after confirming the referenced global specialty exists. Do not call this if a tenant specialty for the same specialty already exists for the tenant (check with `GET /tenant-specialties` first) — this operation does not check for an existing record and is not idempotent; submitting the same payload twice creates a second, duplicate record.


        **How to call it:** Supply the required `tenant-id` header. The request body must include a non-empty `specialtyId`; a missing or blank `specialtyId` returns 400 before any other validation occurs. The `data` field is additionally validated against the `TenantSpecialty` JSON Schema; schema violations also return 400. Requires the `CREATE_TENANT_SPECIALTY` permission.


        **What you get back:** On success (201) the created tenant specialty object is returned, including the server-assigned `id`. No `Location` header is emitted.'
      operationId: createTenantSpecialty
      tags:
      - Tenant Specialty
      parameters:
      - description: Tenant identifier that owns the new record.
        required: true
        name: tenant-id
        in: header
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateTenantSpecialtyRequest'
        required: true
      responses:
        '401':
          description: Unauthorized - the request is missing a valid JWT.
        '403':
          description: Forbidden - the caller lacks the CREATE_TENANT_SPECIALTY permission for this tenant.
        '500':
          description: Internal Server Error - an unexpected error occurred while creating the record.
        '201':
          description: The newly created tenant specialty, including its server-assigned `id`. No `Location` header is returned.
          content:
            application/json:
              examples:
                tenantSpecialtyCreated:
                  value:
                    id: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                    tenantId: acme-health
                    specialtyId: 9c858901-8a57-4791-81fe-4c455b099bc9
                    data:
                      displayName: Cardiology
                      description: Diagnosis and treatment of heart conditions.
                      changeReason: Initial tenant onboarding
              schema:
                type: object
                properties:
                  id:
                    type: string
                  tenantId:
                    type: string
                  specialtyId:
                    type: string
                  data:
                    $ref: https://schemas.certifyos.com/entities/TenantSpecialty.schema.json
                    type: object
        '400':
          description: Missing `tenant-id` header, missing/blank `specialtyId`, or `data` failing TenantSpecialty JSON Schema validation.
          content:
            application/json:
              examples:
                missingTenantIdHeader:
                  value:
                    errors:
                    - httpStatus: 400
                      reason: VALIDATION_ERROR
                      title: 'Validation failed for field: createTenantSpecialty.tenantId'
                      detail: must not be null
                missingSpecialtyId:
                  value:
                    error: Specialty ID is required
                invalidSchemaData:
                  value:
                    error: 'Invalid request data: $.data.displayName: is missing but it is required'
      security:
      - jwt: []
  /tenant-specialties/by-classification:
    get:
      summary: List tenant specialties matching a classification and category
      description: 'Returns tenant specialties for the current tenant that belong to a given classification source and category within that source.


        **What it does:** Filters the tenant''s specialty list by a classification taxonomy. For example, a classification source of `nucc` combined with a category of `Individual` returns only specialties belonging to that NUCC grouping. Both parameters are required, free-text strings — they are not validated against an enum or fixed value set, either in this service or the data layer.


        **Aggregating across sources:** Pass `classificationSource=ALL` to return specialties matching the given `category` across every classification source configured for the tenant. Results are not deduplicated: the same specialty can legitimately belong to more than one classification source, and each occurrence is returned. `ALL` is handled by the underlying data layer, not validated or special-cased here — any other free-text value is still passed through unchanged, as before.


        **Sort order:** Results are always returned sorted by specialty display name, ascending (case-sensitive, data-layer-enforced). This ordering applies to every `classificationSource` value, including `ALL`, and cannot be overridden by the caller — there is no sort query parameter.


        **When to use:** Use this endpoint when you need specialties scoped to a specific taxonomy rather than the full tenant specialty list. Use `GET /tenant-specialties` when you need all specialties regardless of classification.


        **How to call it:** Supply the required `tenant-id` header plus both `classificationSource` and `category` query parameters. Omitting either returns 400. Requires the `READ_TENANT_SPECIALTY` permission.


        **What you get back:** A list of matching tenant specialty objects, sorted by display name ascending (see above), each including its `classificationSource`, `specialtyCategory`, and `taxonomyCode`. Results are served from a cache with a 5-minute TTL that is not invalidated on writes — a specialty created, updated, or deleted (including changes that affect `ALL`''s aggregated set) may take up to 5 minutes to be reflected here.'
      operationId: getTenantSpecialtiesByClassification
      tags:
      - Tenant Specialty
      parameters:
      - description: Category to filter by within the classification source (e.g. "Individual"). Free text — not restricted to a fixed set of values.
        example: Individual
        in: query
        required: true
        name: category
        schema:
          type: string
      - description: Classification source to filter by (e.g. "nucc"), or the special value "ALL" to aggregate specialties across every classification source for the tenant (not deduplicated — the same specialty may appear once per source it belongs to). Otherwise free text — not restricted to a fixed set of values.
        example: nucc
        in: query
        required: true
        name: classificationSource
        schema:
          type: string
      - description: Tenant identifier that scopes the query.
        required: true
        name: tenant-id
        in: header
        schema:
          type: string
      responses:
        '401':
          description: Unauthorized - the request is missing a valid JWT.
        '403':
          description: Forbidden - the caller lacks the READ_TENANT_SPECIALTY permission for this tenant.
        '500':
          description: Internal Server Error - an unexpected error occurred while retrieving the list.
        '200':
          description: The tenant specialties matching the given classification source (or, for `classificationSource=ALL`, the union across all sources, not deduplicated) and category, sorted by display name ascending. May reflect data up to 5 minutes stale (see caching note above).
          content:
            application/json:
              examples:
                tenantSpecialtiesByClassification:
                  value:
                    totalCount: 1
                    data:
                    - displayName: Cardiology
                      description: Diagnosis and treatment of heart conditions.
                      changeReason: Initial tenant onboarding
              schema:
                $ref: '#/components/schemas/GetTenantSpecialtiesResponse'
        '400':
          description: Missing `tenant-id` header, `classificationSource`, or `category`.
          content:
            application/json:
              examples:
                missingClassificationSource:
                  value:
                    errors:
                    - httpStatus: 400
                      reason: VALIDATION_ERROR
                      title: 'Validation failed for field: classificationSource'
                      detail: must not be null
              schema:
                $ref: '#/components/schemas/ApiError'
      security:
      - jwt: []
  /tenant-specialties/{id}:
    put:
      summary: Replace a tenant specialty's data in full
      description: 'Replaces the stored data for an existing tenant specialty. This is a full-replacement operation — fields not included in the request body are cleared, not preserved.


        **What it does:** Overwrites the tenant specialty identified by `{id}` with the supplied payload. The data layer performs a replace, not a merge, so callers must supply all fields they wish to retain.


        **When to use:** Use this to update any attribute of a tenant specialty after it has been created.


        **How to call it:** Supply the required `tenant-id` header and the tenant specialty `id` as a path segment (an opaque, server-assigned string). The request body is validated against the `TenantSpecialty` JSON Schema on the `data` field; validation failures return 400. The same request schema is used as for `POST`. Requires the `UPDATE_TENANT_SPECIALTY` permission. Returns 404 if no specialty with the given `id` exists for the supplied `tenant-id` — the record is looked up before any write is attempted.


        **What you get back:** On success (200) the full updated tenant specialty object is returned. This operation is idempotent — sending the same payload twice produces the same state.'
      operationId: updateTenantSpecialty
      tags:
      - Tenant Specialty
      parameters:
      - description: Opaque, server-assigned identifier of the tenant specialty to replace.
        in: path
        required: true
        name: id
        schema:
          type: string
      - description: Tenant identifier that scopes the update.
        required: true
        name: tenant-id
        in: header
        schema:
          type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateTenantSpecialtyRequest'
        required: true
      responses:
        '401':
          description: Unauthorized - the request is missing a valid JWT.
        '403':
          description: Forbidden - the caller lacks the UPDATE_TENANT_SPECIALTY permission for this tenant.
        '500':
          description: Internal Server Error - an unexpected error occurred while replacing the record.
        '200':
          description: The full tenant specialty object after replacement.
          content:
            application/json:
              examples:
                tenantSpecialtyReplaced:
                  value:
                    id: 3fa85f64-5717-4562-b3fc-2c963f66afa6
                    tenantId: acme-health
                    specialtyId: 9c858901-8a57-4791-81fe-4c455b099bc9
                    data:
                      displayName: Cardiology
                      description: Diagnosis and treatment of heart conditions, updated.
                      changeReason: Corrected description
              schema:
                type: object
                properties:
                  id:
                    type: string
                  tenantId:
                    type: string
                  specialtyId:
                    type: string
                  data:
                    $ref: https://schemas.certifyos.com/entities/TenantSpecialty.schema.json
                    type: object
        '400':
          description: Missing `tenant-id` header, or `data` failing TenantSpecialty JSON Schema validation.
          content:
            application/json:
              examples:
                missingTenantIdHeader:
                  value:
                    errors:
                    - httpStatus: 400
                      reason: VALIDATION_ERROR
                      title: 'Validation failed for field: updateTenantSpecialty.tenantId'
                      detail: must not be null
                invalidSchemaData:
                  value:
                    error: 'Invalid request data: $.data.displayName: is missing but it is required'
        '404':
          description: No tenant specialty exists with the given `id` for the supplied `tenant-id`.
          content:
            application/json:
              examples:
                tenantSpecialtyNotFound:
                  value:
                    error: Resource not found
      security:
      - jwt: []
    get:
      summary: Fetch a single tenant specialty by its ID
      description: 'Returns the detail of a single tenant specialty record belonging to the tenant identified by the `tenant-id` header.


        **What it does:** Retrieves one tenant specialty by its unique identifier, including its tenant-specific metadata (display name, description, change reason).


        **When to use:** Use this when you already hold the `id` of a tenant specialty (for example, from a prior `GET /tenant-specialties` response) and need its detail. Do not use this as a lookup-by-name or lookup-by-classification — use the list or by-classification endpoints for those.


        **How to call it:** Supply the required `tenant-id` header and the tenant specialty `id` as a path segment. `id` is an opaque, server-assigned string (assigned as a UUIDv4 by the data layer at creation time); the API does not otherwise constrain its format. Requires the `READ_TENANT_SPECIALTY` permission.


        **What you get back:** The tenant specialty''s entity content (display name, description, change reason) on 200. Returns 404 if no specialty with the given `id` exists for the supplied `tenant-id`.'
      operationId: getTenantSpecialty
      tags:
      - Tenant Specialty
      parameters:
      - description: Opaque, server-assigned identifier of the tenant specialty to retrieve.
        in: path
        required: true
        name: id
        schema:
          type: string
      - description: Tenant identifier that scopes the lookup.
        required: true
        name: tenant-id
        in: header
        schema:
          type: string
      responses:
        '401':
          description: Unauthorized - the request is missing a valid JWT.
        '403':
          description: Forbidden - the caller lacks the READ_TENANT_SPECIALTY permission for this tenant.
        '500':
          description: Internal Server Error - an unexpected error occurred while retrieving the record.
        '200':
          description: The tenant specialty matching the given `id`.
          content:
            application/json:
              examples:
                tenantSpecialty:
                  value:
                    data:
                      displayName: Cardiology
                      description: Diagnosis and treatment of heart conditions.
                      changeReason: Initial tenant onboarding
              schema:
                $ref: '#/components/schemas/GetTenantSpecialtyResponse'
        '404':
          description: No tenant specialty exists with the given `id` for the supplied `tenant-id`.
          content:
            application/json:
              examples:
                tenantSpecialtyNotFound:
                  value:
                    error: Resource not found
      security:
      - jwt: []
    delete:
      summary: Remove a specialty from the tenant's configuration
      description: 'Permanently removes a tenant specialty record from the tenant''s configuration. This is a hard delete — the row is removed, not flagged inactive — and cannot be undone.


        **What it does:** Deletes the tenant specialty identified by `{id}` under the tenant identified by the `tenant-id` header. If the specialty is still referenced by a practitioner-specialty or facility-specialty association, the delete is rejected by a database-level constraint and surfaces as 400 (see below) rather than succeeding or cascading. Deleting a specialty that is only referenced by a tenant-group-specialty association is **not** blocked and will leave that association pointing at a deleted record.


        **When to use:** Use this when a specialty is no longer applicable to the tenant and should be removed from all specialty selection surfaces. Verify the specialty is not actively assigned to a practitioner or facility before calling, since the request will otherwise fail. This operation is not idempotent: calling it a second time for the same `id` returns 404, not another 204.


        **How to call it:** Supply the required `tenant-id` header and the tenant specialty `id` as a path segment (an opaque, server-assigned string). Requires the `DELETE_TENANT_SPECIALTY` permission.


        **What you get back:** Returns 204 with no response body on success. Returns 404 if no specialty with the given `id` exists for the supplied `tenant-id`. Returns 400 if the specialty is still referenced by a practitioner-specialty or facility-specialty association.'
      operationId: deleteTenantSpecialty
      tags:
      - Tenant Specialty
      parameters:
      - description: Opaque, server-assigned identifier of the tenant specialty to delete.
        in: path
        required: true
        name: id
        schema:
          type: string
      - description: Tenant identifier that scopes the delete.
        required: true
        name: tenant-id
        in: header
        schema:
          type: string
      responses:
        '401':
          description: Unauthorized - the request is missing a valid JWT.
        '403':
          description: Forbidden - the caller lacks the DELETE_TENANT_SPECIALTY permission for this tenant.
        '500':
          description: Internal Server Error - an unexpected error occurred while deleting the record.
        '204':
          description: The tenant specialty was permanently deleted.
        '400':
          description: Missing `tenant-id` header, or the specialty is still referenced by a practitioner-specialty or facility-specialty association and cannot be deleted.
          content:
            application/json:
              examples:
                missingTenantIdHeader:
                  value:
                    errors:
                    - httpStatus: 400
                      reason: VALIDATION_ERROR
                      title: 'Validation failed for field: deleteTenantSpecialty.tenantId'
                      detail: must not be null
                specialtyInUse:
                  value:
                    error: Invalid request data
        '404':
          description: No tenant specialty exists with the given `id` for the supplied `tenant-id`.
          content:
            application/json:
              examples:
                tenantSpecialtyNotFound:
                  value:
                    error: Resource not found
      security:
      - jwt: []
components:
  schemas:
    CreateTenantSpecialtyRequest:
      type: object
      required:
      - specialtyId
      properties:
        specialtyId:
          type: string
          description: Identifier of the global specialty this tenant specialty is based on. Required and must reference an existing global specialty; a missing or blank value is rejected with 400 before any other validation runs.
        data:
          $ref: https://schemas.certifyos.com/entities/TenantSpecialty.schema.json
          type: object
          description: Tenant-specific metadata for this specialty (e.g. display name, description, change reason). Validated against the TenantSpecialty JSON Schema; on PUT this value fully replaces any previously stored data — fields omitted here are cleared, not preserved.
    ApiError:
      type: object
      description: Standard API error response containing a list of error objects
      properties:
        errors:
          type: array
          items:
            $ref: '#/components/schemas/ErrorObject'
          description: List of error objects describing validation or processing failures
    GetTenantSpecialtyResponse:
      type: object
      properties:
        data:
          $ref: https://schemas.certifyos.com/entities/TenantSpecialty.schema.json
          type: object
          description: The tenant specialty record.
    GetTenantSpecialtiesResponse:
      type: object
      properties:
        totalCount:
          type: integer
          format: int64
          description: Total number of tenant specialty records matching the query, before pagination. Note the underlying list endpoints return at most a single fixed page of results, so this may exceed the number of items in `data`.
        data:
          type: array
          items:
            $ref: https://schemas.certifyos.com/entities/TenantSpecialty.schema.json
            type: object
            properties:
              jsonNode:
                $ref: '#/components/schemas/JsonNode'
          description: The page of matching tenant specialty records.
    ErrorObject:
      type: object
      description: Individual error object containing details about a specific validation or processing error
      properties:
        httpStatus:
          type: integer
          format: int32
          examples:
          - 400
          description: HTTP status code for this error
        reason:
          type: string
          examples:
          - VALIDATION_ERROR
          description: Error reason/code
        title:
          type: string
          examples:
          - 'Validation failed for field: eventTypes'
          description: Error title/summary
        detail:
          type: string
          examples:
          - eventTypes is required and cannot be empty or null
          description: Detailed error message
        rejectedValue:
          type: string
          description: The value that was rejected, omitted for sensitive fields such as SSN
    JsonNodeType:
      type: string
      enum:
      - ARRAY
      - BINARY
      - BOOLEAN
      - MISSING
      - 'NULL'
      - NUMBER
      - OBJECT
      - POJO
      - STRING
    JsonNode:
      type: object
      properties:
        empty:
          type: boolean
        valueNode:
          type: boolean
        containerNode:
          type: boolean
        missingNode:
          type: boolean
        array:
          type: boolean
        object:
          type: boolean
        nodeType:
          $ref: '#/components/schemas/JsonNodeType'
        pojo:
          type: boolean
        number:
          type: boolean
        integralNumber:
          type: boolean
        floatingPointNumber:
          type: boolean
        short:
          type: boolean
        int:
          type: boolean
        long:
          type: boolean
        float:
          type: boolean
        double:
          type: boolean
        bigDecimal:
          type: boolean
        bigInteger:
          type: boolean
        textual:
          type: boolean
        boolean:
          type: boolean
        'null':
          type: boolean
        binary:
          type: boolean
  securitySchemes:
    jwt:
      type: http
      description: JWT Authentication - Provide only the raw token without Bearer prefix
      scheme: bearer
      bearerFormat: JWT
x-provenance:
  method: harvested
  publisher: Certifyos
  source: https://api-service.internal.certifyos.com/openapi.json
  note: split by refine-openapis from the provider's own published document, verified by fetch (openapi/_original/*.fetch.json);
    stamped by stamp-openapi-provenance.py (roadmap#793)