Trust begins before the first conversation.

Empowering your health · Empowering your life

00000%100

VITALES DEVELOPERS · API v1

Connect your systems. Keep access intentional.

A practical integration guide for clinic developers: read appointments and explicitly authorized patient snapshots with revocable, account-scoped keys.

01 · Quick start

  1. Sign in as the practitioner or clinic account that owns the appointments. Open Settings → Integrations → Vitales API.
  2. Enter a partner name, an authorized purpose and a lifetime of 1–90 days. Create one key per partner. Appointment access is read-only and bound to your account.
  3. For medical snapshots, explicitly enable FHIR, enter one linked patient UID, reference the authorization document and attest that sharing is authorized. This is a professional attestation, not automated legal or patient-consent verification.
  4. Copy the key once into your partner’s server-side secret manager. Also provide the tenant ID and owner UID shown in Vitales. Keys cannot be retrieved later; replace a lost key.

appointments.read

Account-owned appointments

fhir.read

Opt-in · one authorized patient

02 · Authentication

Every partner read requires HTTPS and both headers below. A UID is an identifier, never a password. The API verifies the key’s tenant, owner, role, scope, expiry and revocation.

Base URL: https://vitales-nest-backend-424459202857.us-central1.run.app
Authorization: Bearer YOUR_VITALES_API_KEY
x-tenant-id: YOUR_TENANT_ID

The owner manages credentials inside Vitales using their private Firebase sign-in session. Never give that session token to a partner. Integration keys cannot create other keys. Do not enter real keys into shared Swagger sessions or recordings.

Owner credential lifecycle endpoints
POST   /integrations/v1/credentials
GET    /integrations/v1/credentials
DELETE /integrations/v1/credentials/{credentialId}

// Owner Firebase ID token + x-tenant-id, NOT a partner key
{
  "label": "Clinic scheduling connector",
  "purposeOfUse": "Authorized appointment synchronization",
  "expiresInDays": 30
}

// Optional fields for one patient’s FHIR scope:
// fhirPatientUid, consentAttested: true, consentEvidence

The creation response includes apiKey once, id, ownerUid, tenantId, scopes and expiresAt. Listing never returns the secret or its hash. Revocation is owner-only. At most five new keys per account per UTC day; the list returns up to 100 keys, so retain each credential id.

03 · Appointments

curl --get 'https://vitales-nest-backend-424459202857.us-central1.run.app/appointment-query/user/OWNER_UID/everything' \
  -H "Authorization: Bearer $VITALES_API_KEY" \
  -H "x-tenant-id: $VITALES_TENANT_ID" \
  --data-urlencode 'limit=50'

OWNER_UID must be the practitioner or clinic that issued the key. Clinic keys read only appointments explicitly owned by that clinic; practitioner keys read assigned appointments. Linked accounts do not grant blanket export access.

{
  "apiVersion": "1",
  "ownerUid": "OWNER_UID",
  "appointments": [
    {
      "id": "appointment_001",
      "practitionerUid": "PRACTITIONER_UID",
      "clinicUid": null,
      "patientUid": "PATIENT_UID",
      "status": "booked",
      "start": "2026-11-01T15:00:00.000Z",
      "end": "2026-11-01T15:30:00.000Z",
      "createdAt": null,
      "updatedAt": "2026-10-15T12:00:00.000Z"
    }
  ],
  "page": {
    "scannedCount": 50,
    "returnedCount": 1,
    "nextCursor": "NEXT_CURSOR",
    "hasMore": true
  }
}

Only identifiers, normalized status and UTC timestamps are returned. No patient names, email, phone, medical notes, payment details or video-call URLs. A missing clinic UID or legacy timestamp can be null.

Optional query parameters
limit1–100 source records per page; default 50. Not a guaranteed number of matches.
cursorUse page.nextCursor without changing the other filters.
start / endISO timestamps with timezone; supply both, maximum 31 days. Start inclusive, end exclusive.
updatedSinceInclusive ISO watermark; undated legacy records are also included.

04 · Medical records · FHIR

First configure one enabled Google Healthcare FHIR integration in the owner account and synchronize the patient. Use a key with fhir.read explicitly bound to that patient, documented sharing authorization, and a current reciprocal patient relationship in the same tenant.

curl 'https://vitales-nest-backend-424459202857.us-central1.run.app/integrations/v1/fhir/patient/PATIENT_VITALES_UID' \
  -H "Authorization: Bearer $VITALES_API_KEY" \
  -H "x-tenant-id: $VITALES_TENANT_ID"
{
  "resourceType": "Bundle",
  "type": "collection",
  "timestamp": "2026-11-01T12:00:00.000Z",
  "entry": [
    {
      "fullUrl": "https://healthcare.googleapis.com/.../fhir/Patient/FHIR_PATIENT_ID",
      "resource": {
        "resourceType": "Patient",
        "id": "FHIR_PATIENT_ID",
        "identifier": [
          {
            "system": "https://vitales.life/identifiers/user-uid",
            "value": "PATIENT_VITALES_UID"
          }
        ]
      }
    }
  ]
}

This illustrative response omits clinical fields. Actual snapshots can contain sensitive health and identity data. The endpoint exports only mapped Patient, Observation, Encounter and Procedure resources, at most 100 resources / 8 MB, with a 20-second resource-read budget. The mapped Patient identifier and each clinical subject are checked. Unsupported stores, incomplete mappings or failed reads produce an error, never a partial success.

Snapshot ≠ complete medical history

This is not a full $everything operation, a live export of unsynchronized Vitales records, a general FHIR proxy, SMART-on-FHIR, bulk export, or a certification. Conditions, medications, immunizations and attachments are not exported by this snapshot. Never treat absent resources as absent clinical findings.

The legacy /fhir-query/patient/{id}/everything endpoint has been removed. Use /integrations/v1/fhir/patient/{uid} with the Vitales patient UID and an authorized patient-specific key. Raw Patient/Observation/Encounter readers are unavailable.

HL7 FHIR R4 Bundle reference · HL7 $everything reference

05 · Reliable synchronization

  1. Capture a UTC watermark before polling. Fetch every page, even when appointments is empty but hasMore is true.
  2. Upsert by stable appointment id. Rescheduling and cancellation update that same id; keep the latest status and timestamps.
  3. For later polls use updatedSince with a small overlap and deduplicate. Omit start/end so appointments moved outside a date window are not lost. Advance your checkpoint only after all pages succeed.
  4. Periodically reconcile a complete unfiltered listing. Pagination is not a transactional snapshot, and hard deletions have no tombstones. This API does not provide webhooks, appointment writes, two-way sync or automatic vendor delivery.

06 · Errors & limits

400

Invalid fields, dates, range or cursor. Correct the request before retrying.

401

Missing, expired, revoked or invalid key/tenant, or unavailable scope. Check headers and rotate if needed.

403 / 404

Wrong owner/patient, missing current relationship, missing authorization or unavailable mapping. Do not probe identifiers.

429

60 reads per key per UTC minute, shared across appointment and FHIR requests. Back off with jitter; avoid tight polling.

503

Unreadable appointment or unavailable FHIR export. Retry with bounded backoff and preserve the last successful checkpoint; never interpret this as record deletion.

07 · Security checklist

  • Use a backend secret manager. Never commit keys or place them in browser/mobile bundles, URLs, analytics, screenshots or logs.
  • Rotate before expiry: create replacement → switch partner → verify → revoke old key. Revoke immediately if compromised or sharing authorization is withdrawn. Previously exported data cannot be recalled by revocation.
  • Review current authorization, patient relationship, purpose, data minimization, recipient security and retention before sharing. Vitales records the issuer’s attestation; it does not automatically establish legal permission or track external consent withdrawal.
  • Test with synthetic data first. Do not send health data, keys or Google service-account credentials to support.

Doctoralia, Saludtools, NextGen and other systems need their own compatible authorized connector. Providing this API does not imply an existing partnership, automatic integration or regulatory certification.

admin@vitales.life