Skip to main content

Overview

All Parchment Health API endpoints follow a consistent response structure to ensure predictability and ease of integration. Our responses comply with industry standards including RFC 7807 for error handling.

Response Structure

Success Response Format

All successful API responses follow this structure:
{
  "success": true,
  "statusCode": 200,
  "message": "Success",
  "data": {
    // Response-specific data
  },
  "timestamp": "2024-01-15T10:30:00.000Z",
  "requestId": "req_1705312200000_abc123",
  "pagination": {
    // Only included for list operations
    "count": 25,
    "hasNext": true,
    "limit": 50,
    "offset": 0,
    "lastKey": "eyJwayI6ICJQQVRJRU5UIzIwYjA0OTM0LTJjZTUtNDYyOC1iYzZlLWVhMWNkM2I3MjllMyIsICJzayI6ICIyMDI1LTA1LTAyVDA1OjU5OjI3LjM0NFo..."
  }
}

Error Response Format (RFC 7807)

All error responses follow the RFC 7807 Problem Details standard:
{
  "success": false,
  "statusCode": 400,
  "error": {
    "type": "https://parchment.health/errors/validation-error",
    "title": "Validation failed",
    "detail": "There were some problems with your input.",
    "instance": "/patients/123",
    "validation": [
      {
        "field": "family_name",
        "message": "Family name is required",
        "code": "VALIDATION_ERROR"
      }
    ]
  },
  "timestamp": "2024-01-15T10:30:00.000Z",
  "requestId": "req_1705312200000_def456"
}

HTTP Status Codes

Success Codes

CodeStatusUsage
200OKSuccessful GET, PUT, PATCH operations
201CreatedSuccessful POST operations (resource creation)
202AcceptedRequest accepted for processing (e.g., conflicts found)
204No ContentSuccessful DELETE operations

Error Codes

CodeStatusUsage
400Bad RequestInvalid request data or parameters
401UnauthorizedAuthentication required or failed
403ForbiddenAuthorization failed (insufficient permissions)
404Not FoundRequested resource does not exist
409ConflictBusiness logic conflict (e.g., duplicate IDs)
422Unprocessable EntityValidation errors in request data
429Too Many RequestsRate limiting exceeded
500Internal Server ErrorUnexpected server error
503Service UnavailableExternal service temporarily unavailable

Response Fields

Core Fields

FieldTypeDescription
successbooleanIndicates if the request was successful
statusCodenumberHTTP status code
messagestringHuman-readable message (success responses)
dataobjectResponse payload (success responses)
errorobjectError details (error responses)
timestampstringISO 8601 timestamp of the response
requestIdstringUnique identifier for request tracing

Optional Fields

FieldTypeDescription
paginationobjectPagination information for list operations

Pagination Object Fields

FieldTypeDescription
countnumberNumber of items returned in the current page
hasNextbooleanWhether more items are available on subsequent pages
limitnumberMaximum number of items per page (as requested)
offsetnumberStarting position of the current page (zero-based)
lastKeystring|nullOpaque cursor for fetching the next page. Use this value as the lastKey query parameter for the next request. If null, no more pages are available

Error Object Fields

FieldTypeDescription
typestringURI identifying the problem type
titlestringHuman-readable summary of the problem
detailstringHuman-readable explanation
instancestringURI reference to the specific occurrence
validationarrayField-level validation errors (422 responses)

Error Types

Standard Error Types

Error TypeDescription
invalid-requestGeneral invalid request format
missing-required-fieldRequired field not provided
invalid-formatData format validation failed
authentication-requiredAuthentication token missing
invalid-tokenAuthentication token invalid
token-expiredAuthentication token expired
insufficient-scopeMissing required permissions
access-deniedAccess to resource denied
resource-not-foundGeneral resource not found
patient-not-foundSpecific patient not found
resource-conflictGeneral resource conflict
partner-patient-id-conflictPartner patient ID already exists
validation-errorRequest validation failed
business-rule-violationBusiness logic constraint violated
rate-limit-exceededToo many requests
internal-errorUnexpected server error
service-unavailableExternal service unavailable

Response Examples

Create Patient Success (201)

{
  "success": true,
  "statusCode": 201,
  "message": "Patient created successfully",
  "data": {
    "external_patient_id": "PARTNER#12345",
    "parchment_patient_id": "pat_abc123def456",
    "url": "https://app.parchment.health/dashboard/patients/pat_abc123def456"
  },
  "timestamp": "2024-01-15T10:30:00.000Z",
  "requestId": "req_1705312200000_abc123"
}

Get Patient Success (200)

{
  "success": true,
  "statusCode": 200,
  "message": "Success",
  "data": {
    "patient_id": "pat_abc123def456",
    "family_name": "Smith",
    "given_name": "John",
    "date_of_birth": "1990-01-15",
    "sex": "M",
    "ihi_number": "8003608166690503",
    "medicare_number": "1234567890",
    "partner_patient_id": "PARTNER#12345"
  },
  "timestamp": "2024-01-15T10:30:00.000Z",
  "requestId": "req_1705312200000_def456"
}

List Patients Success (200)

{
  "success": true,
  "statusCode": 200,
  "message": "Success",
  "data": [
    {
      "patient_id": "pat_abc123def456",
      "family_name": "Smith",
      "given_name": "John"
    }
  ],
  "timestamp": "2024-01-15T10:30:00.000Z",
  "requestId": "req_1705312200000_ghi789",
  "pagination": {
    "count": 1,
    "hasNext": false,
    "limit": 50,
    "offset": 0,
    "lastKey": null
  }
}

Validation Error (422)

{
  "success": false,
  "statusCode": 422,
  "error": {
    "type": "https://parchment.health/errors/validation-error",
    "title": "Validation failed",
    "detail": "There were some problems with your input.",
    "validation": [
      {
        "field": "family_name",
        "message": "Family name is required",
        "code": "VALIDATION_ERROR"
      },
      {
        "field": "date_of_birth",
        "message": "Invalid date format. Use YYYY-MM-DD",
        "code": "INVALID_FORMAT"
      }
    ]
  },
  "timestamp": "2024-01-15T10:30:00.000Z",
  "requestId": "req_1705312200000_jkl012"
}

Unauthorized Error (401)

{
  "success": false,
  "statusCode": 401,
  "error": {
    "type": "https://parchment.health/errors/authentication-required",
    "title": "Unauthorized",
    "detail": "Valid authentication token is required"
  },
  "timestamp": "2024-01-15T10:30:00.000Z",
  "requestId": "req_1705312200000_mno345"
}

Partner Patient ID Conflict (409)

{
  "success": false,
  "statusCode": 409,
  "error": {
    "type": "https://parchment.health/errors/partner-patient-id-conflict",
    "title": "Partner patient ID conflict",
    "detail": "Partner patient ID 'PARTNER#12345' is already in use by another patient. Please use a unique identifier."
  },
  "timestamp": "2024-01-15T10:30:00.000Z",
  "requestId": "req_1705312200000_pqr678"
}

Patient Not Found (404)

{
  "success": false,
  "statusCode": 404,
  "error": {
    "type": "https://parchment.health/errors/patient-not-found",
    "title": "Patient not found",
    "detail": "Patient with ID 'pat_invalid123' does not exist",
    "instance": "/patients/pat_invalid123"
  },
  "timestamp": "2024-01-15T10:30:00.000Z",
  "requestId": "req_1705312200000_stu901"
}

Internal Server Error (500)

{
  "success": false,
  "statusCode": 500,
  "error": {
    "type": "https://parchment.health/errors/internal-error",
    "title": "Internal server error",
    "detail": "An unexpected error occurred while processing your request"
  },
  "timestamp": "2024-01-15T10:30:00.000Z",
  "requestId": "req_1705312200000_vwx234"
}

Request Tracing

Every response includes a unique requestId that can be used for:
  • Debugging: Reference this ID when reporting issues
  • Logging: Correlate requests across different systems
  • Monitoring: Track request flow through the system
Example: req_1705312200000_abc123

API Versioning

The API version information is tracked internally for compatibility purposes, allowing for:
  • Backward Compatibility: Maintain support for older integrations
  • Feature Detection: Identify available features based on version
  • Migration Planning: Plan upgrades to newer API versions

Pagination Usage

When working with paginated endpoints, use the lastKey field to navigate through pages:

Making Paginated Requests

// First request (no lastKey)
const firstPage = await fetch(`/api/v1/patients?limit=20`);
const firstResponse = await firstPage.json();

// Check if more pages exist
if (firstResponse.pagination.hasNext && firstResponse.pagination.lastKey) {
  // Request next page using lastKey
  const secondPage = await fetch(`/api/v1/patients?limit=20&lastKey=${encodeURIComponent(firstResponse.pagination.lastKey)}`);
  const secondResponse = await secondPage.json();
}

Pagination Best Practices

  1. Always check hasNext before requesting the next page
  2. Use lastKey for cursor-based pagination when available
  3. Fall back to offset for offset-based pagination when needed
  4. URL encode lastKey values when using as query parameters
  5. Handle null lastKey as indication of no more pages

Best Practices

Error Handling

  1. Always check the success field to determine if the request succeeded
  2. Use statusCode for programmatic handling of different scenarios
  3. Display error.detail to users for human-readable error messages
  4. Log requestId for debugging and support requests
  5. Handle validation errors by checking the error.validation array

Integration Tips

  1. Store requestId in your logs for easier debugging
  2. Implement retry logic for 5xx errors with exponential backoff
  3. Cache successful responses when appropriate to reduce API calls
  4. Monitor response times for performance tracking
  5. Validate API version compatibility when integrating

Migration Guide

From Legacy Responses

If you’re migrating from the legacy response format:
  1. Update success checks: Use response.success instead of checking statusCode < 400
  2. Extract data: Access response data from response.data instead of the root
  3. Handle errors: Use response.error object instead of response.message
  4. Add request tracing: Store response.requestId for debugging

TypeScript Support

interface ApiResponse<T = any> {
  success: true
  statusCode: number
  message: string
  data: T
  timestamp: string
  requestId: string
  pagination?: PaginationInfo
}

interface PaginationInfo {
  count: number
  hasNext: boolean
  limit: number
  offset: number
  lastKey: string | null
}

interface ApiErrorResponse {
  success: false
  statusCode: number
  error: {
    type: string
    title: string
    detail: string
    instance?: string
    validation?: ValidationError[]
  }
  timestamp: string
  requestId: string
}