Errors & Troubleshooting

OpesCare uses standard HTTP status codes and returns a consistent JSON error body for every failure. Always check the error field for a machine-readable code and the message field for a human-readable explanation.

Error Response Format

{
  "error": "invalid_scope",
  "message": "The requested scope 'patient:records:write' is not permitted for this client.",
  "status": 403
}

HTTP Status Codes

StatusMeaningCommon Causes
200OKRequest succeeded
201CreatedResource created (subscriptions, consents)
204No ContentSuccessful deletion (webhook unsubscribe)
400Bad RequestMissing required fields, malformed JSON, invalid date format
401UnauthenticatedToken missing, expired, or malformed — re-authenticate
403ForbiddenInsufficient scope, consent not granted, sandbox restriction
404Not FoundPatient not found, invalid health ID, resource deleted
409ConflictDuplicate webhook subscription endpoint
422UnprocessableValidation failed — wrong data type, value out of range
429Rate LimitedToo many requests — back off and retry after the Retry-After header value
500Server ErrorUnexpected server error — check the status page

Machine-Readable Error Codes

Error CodeHTTPDescriptionFix
invalid_client401Wrong client_id or client_secretCheck credentials in the developer portal
token_expired401Bearer token has expired (1-hour TTL)Request a new token using client_credentials grant
token_invalid401Malformed or revoked tokenRe-authenticate from scratch
invalid_scope403Scope not granted to your clientCheck allowed scopes in the developer portal
consent_required403Patient has not granted consent to your clientCall the consent/grant endpoint first
patient_not_found404No patient matches the given Health IDVerify the Health ID is in the correct format (OPC-YYYY-XXXXX)
facility_not_found404Facility ID does not existVerify your facility ID in the developer portal
bridge_token_invalid401Bridge token missing or revokedRe-generate the bridge token in the developer portal
sdk_token_inactive401SDK token has been deactivatedGenerate a new SDK token in the portal
rate_limit_exceeded429Too many requests in a short windowRespect the Retry-After response header
sandbox_only403Your account is restricted to sandboxRequest production access via the developer portal

Error Handling Best Practices

$response = Http::withToken($token)
    ->get('https://opescare.test/api/v1/connect/patient/search', [
        'health_id' => $healthId,
    ]);

if ($response->status() === 401) {
    // Re-fetch token and retry once
    $token    = getNewToken();
    $response = Http::withToken($token)
        ->get('https://opescare.test/api/v1/connect/patient/search', [
            'health_id' => $healthId,
        ]);
}

if ($response->failed()) {
    $error = $response->json();
    // $error['error'] is the machine-readable code
    // $error['message'] is the human-readable description
    throw new \RuntimeException("OpesCare error: {$error['error']} — {$error['message']}");
}

$patient = $response->json();
async function searchPatient(healthId, token) {
  const res = await fetch(
    `https://opescare.test/api/v1/connect/patient/search?health_id=${healthId}`,
    { headers: { Authorization: `Bearer ${token}` } }
  );

  if (res.status === 429) {
    const retryAfter = res.headers.get('Retry-After') || 5;
    await new Promise(r => setTimeout(r, retryAfter * 1000));
    return searchPatient(healthId, token); // retry once
  }

  if (!res.ok) {
    const err = await res.json();
    throw new Error(`OpesCare [${err.error}]: ${err.message}`);
  }

  return res.json();
}
import time
import requests

def search_patient(health_id: str, token: str, retry: int = 1):
    resp = requests.get(
        'https://opescare.test/api/v1/connect/patient/search',
        params={'health_id': health_id},
        headers={'Authorization': f'Bearer {token}'},
    )
    if resp.status_code == 429 and retry > 0:
        time.sleep(int(resp.headers.get('Retry-After', 5)))
        return search_patient(health_id, token, retry - 1)
    resp.raise_for_status()
    return resp.json()
If you're hitting persistent 500 errors, check the OpesCare system status page. For integration issues, contact developer support.