Overview
Use the Record Retrieval API to ask Tavrn to retrieve medical records, billing records, and provider invoices from a healthcare facility. The basic flow is:- Create or select a case and, if needed, configure a Requestor profile.
- Upload the signed HIPAA authorization form and any profile documents.
- Create a retrieval request.
- Track the request with webhooks and incremental polling.
- Download records and provider invoices as they become available.
What You’ll Need
- API key with
retrievals:writeandretrievals:readscopes (pluscases:writeif you’ll create the case via the API in step 1) requestors:readif you’ll list or read Requestor profiles;requestors:writeif you’ll create or configure one, including inline creation- A signed HIPAA authorization PDF for the patient
- Patient name (date of birth if available)
- A facility ID from facility search, or the facility name and address
- At least one record type to request
Step-by-Step Guide
1. Create or Select a Case
Every new Enterprise API retrieval request needs a case. If you already have a case, skip to step 2 and use itsid. Otherwise, create one:
id when you create the retrieval request.
You can also create the case in the same call as its first retrieval using
POST /v2/retrieval-requests. Upload files
first using the retrieval upload endpoint, which does not require a case ID.
2. Upload the Authorization Form
Request an upload URL for the signed HIPAA authorization PDF:file_name and file_type for a retrieval
attachment.
Response:
upload_url:
upload_id. You will use it in auth_form when creating the retrieval request.
Upload supporting files the same way, one file per
sign-upload call. Use the returned upload_id values in attachments.3. Create the Retrieval Request
This minimal example requests medical records for one patient from one facility:id. Webhook events reference it as retrieval_request_id, and you use it to fetch status and download returned files.
Both creation endpoints accept patient and requested_records, plus exactly one
of a facility_id from search or a manual facility object:
For organizations with duplicate detection enabled, creation can return
409 duplicate_request_detected with a duplicates array. Review those matches before retrying with "allow_duplicate": true if the new request is intentional.
Find a facility
Search by facility name, alias, phone, fax, address, or NPI using an API key withretrievals:read:
facility object in your creation body with
"facility_id": "facility_example". Send exactly one of facility_id or
facility. If the API reports an invalid or expired facility selection, search
again and use the new ID.
Review any listed requirements before submitting. Each includes a label,
optional description, category (input, document, or instruction), and
applicable record_types; an empty record_types list means all record types.
Document requirements may include template_download_url for a blank template.
The link is valid for 1 hour; repeat the search for a fresh link.
Search text must be 3–200 characters after trimming, with at least 3 alphanumeric
characters. state is optional; limit is 1–10 and defaults to 10. Results are not
paginated. On 429, wait for Retry-After; on 503, try again later.
Select a Requestor
A Requestor is a retrieval profile within your organization: its name, letter of representation, RFC form, affidavits, correspondence settings, and provider invoice approval limit. To use an existing profile, add its ID to the retrieval body:requestor_id and requestor keeps the existing organization
default. Each retrieval retains the selected ID. Configuration updates to that
profile apply to its linked retrievals.
Find available profiles with
GET /v2/requestors,
or read one with
GET /v2/requestors/{requestor_id}.
Both require requestors:read. List responses contain results, next, and
previous; limit defaults to 20 and has a maximum of 100. Each profile
includes is_default. An unavailable profile ID returns 404.
If you need a different name, packet documents, correspondence settings, or
invoice limit, you can create a reusable profile before submitting the
retrieval. Give it a nonblank name using
POST /v2/requestors,
which requires requestors:write:
id and use it
as requestor_id for this and later retrievals. You can also supply an inline
requestor on either retrieval creation endpoint; it requires requestors:write
and cannot be combined with requestor_id.
Upload Requestor Documents
To include a letter of representation in retrieval packets, upload it to the selected profile. A profile without its own document does not use the default profile’s document. Request an upload URL withPOST /v2/requestors/sign-upload,
then PUT the PDF bytes to the returned upload_url:
upload_id in the profile create or update body. Profile
documents must be readable, unencrypted PDFs with a .pdf extension and
application/pdf type, of at most 25 MiB. Upload bytes within 15 minutes; the
upload ID expires after one hour. These upload IDs are for Requestor documents.
Authorization forms and retrieval attachments use the
retrieval upload endpoint.
For example, attach the uploaded letter to an existing profile with
PATCH /v2/requestors/{requestor_id}:
file_name, page_count, and
uploaded_at.
Create a Case and Requestor Inline
UsePOST /v2/retrieval-requests to create the case, Requestor, and retrieval in
one request. This request requires retrievals:write, cases:write, and
requestors:write.
First upload the signed authorization through
POST /v2/retrieval-requests/sign-upload.
For profile documents such as the letter of representation, follow
Upload Requestor Documents.
Both take file_name and file_type; PUT each file to its returned upload_url.
Use each upload ID with the matching document field. Upload the bytes within
15 minutes and use the upload_id within one hour.
case_id, requestor_id, and retrieval id.
Upload files before creating the retrieval. POST creation is not idempotent: each
successful request with an inline case or requestor creates a new one. Retain
the returned IDs and use case_id and requestor_id for subsequent retrievals.
Use case_id instead of case for an existing case, and requestor_id instead of
requestor for an existing profile. Exactly one case choice is required. Do not
send both alternatives for either resource. The case-scoped creation endpoint
continues to use the case in its URL and does not accept an inline case.
Update Requestor Settings
UsePATCH /v2/requestors/{requestor_id}
to update a profile’s settings for linked retrievals. It requires requestors:write
and at least one field. Omitted fields remain unchanged.
Read responses include
effective_provider_invoice_limit, so you can see the
limit used when provider_invoice_limit is null. The API does not delete
profiles, change the organization default, or reassign an existing retrieval
to another profile.
4. Track Status
Subscribe to retrieval request webhooks for status updates, action requests, and available records or invoices:
When an event arrives, use its retrieval request ID to fetch the current request:
status for the overall request state and stage to show its progress in Tavrn.
status values:
completed and cancelled are final statuses. Both trigger a retrieval_request.status_changed event. Continue incremental polling to pick up later document changes.
When
status is action_required, read pending_action_request for what your firm needs to provide. Respond through the API or follow platform_url to handle it in Tavrn. After a response, the request returns to processing.stage values:
stage_label and stage_description carry the exact text shown on the dashboard for the current stage. Not every request passes through every stage — for example, a request whose facility contact is already known goes straight to request_sent.
Example response (abridged):
timeline entry has a state: completed (happened), current (where the request is now), pending (standard step not reached yet), or skipped (standard step that was not needed). checkpoints list individual attempts within a step, such as phone calls. action_request is set on action_required steps and includes what was asked, whether your firm has responded (awaiting_response, answered, or resolved), and the response text.
timeline is returned by GET /v2/retrieval-requests/{id} and list queries with include=details. Summary list results include stage, stage_label, and stage_description but omit the timeline.stage accepts one or more comma-separated values and can be combined with status and case_id.
Incremental polling
Usepublic_updated_since with the list endpoint to reconcile status, action request, and document updates alongside webhooks:
- Start with your saved checkpoint, or the epoch timestamp above for an initial sync.
- Upsert each result by request ID.
include=detailsadds the timeline, open action request, and released document metadata. - Follow each
nextURL as returned until it isnull. - After processing the final page, save its
next_public_updated_sincefor the next round.
public_updated_at when updating a cached request. The final page supplies next_public_updated_since even when no requests were returned.
For an organization-wide sync, leave status, stage, and case filters unset so completed and cancelled requests stay in scope. You can divide a large initial sync into fixed creation-date windows, with a checkpoint for each window.
Choose a polling interval that fits your integration. Changes during a round may appear in that round or the next. If a cursor expires or polling returns 503, resume from the last saved checkpoint. Fetch an individual request when you need current costs.
5. Download Records and Invoices
List documents when you receiveretrieval_request.documents_available or need current files. Provider invoices can become visible before or after request completion:
next and previous are always null. Use category to distinguish records, provider invoice documents, and cost_summary PDFs.
Each invoice entry includes metadata.provider_fee_amount: the invoice amount in USD, not cents, that contributes to costs.provider_fees. 0 is a valid amount. Record and cost summary entries omit metadata. The embedded documents array on GET /v2/retrieval-requests/{id} and the document list use the same entries. A documents_available event’s document_ids and invoice_ids match their id values.
An invoice can appear in the list and costs before it is downloadable. In that
case, its download route returns 404. The invoice documents_available webhook
fires when the file becomes downloadable.
Get a download URL for each document:
download_url before it expires.
Request cost PDF
Once a request iscompleted and its billing is finalized, its documents include
an entry with id and category both set to cost_summary. The PDF shows Tavrn
credits and fees, provider fees, and the total. It always includes a Tavrn credits
line, showing 0 credits × $0.00 = $0.00 when the request has no credit entries.
download_url and expires_in: 3600. Fetch the URL to
download the PDF. The endpoint returns 404 while the document is unavailable.
The entry appears in the request GET response and list results with
include=details, but is excluded from documents_summary counts. Refetch the
request or document list to check availability: billing finalization does not
trigger a documents_available webhook or advance public_updated_at.
Invoice Availability Notifications
Subscribe toretrieval_request.documents_available through
Webhooks to learn when a document becomes downloadable.
When a provider invoice becomes downloadable, the request’s public_updated_at
advances and the event identifies the available invoice:
document_ids and invoice_ids. Use it as {document_id} on the download route, and fetch the request for current document and cost details.
Retrieval documents are separate from case documents you upload for other workflows. Their metadata is available from
/v2/retrieval-requests/{id}/documents, the request GET response, and list queries with include=details. Use the retrieval document download endpoint to access the files.Optional Fields
The minimal request works with patient name, a facility ID or facility name and address, at least one record type, and an authorization form. Add these fields when you have them:Requested Records
Userequested_records to describe what you want from the facility.
Medical records only:
certification or affidavit — across all of its requested_records. Mixing them (on the same or different lines) returns a 400 validation_error; submit a separate request for records that need the other kind.
Ongoing care:
Set service_end_date to null to request records through the present.
Some values, including
rfc, abstract_medical_records, and requirements, are available only when enabled for your organization. See Permission-gated features.Responding to Action Requests
When Tavrn needs something from your firm, the request’sstatus becomes action_required and GET /v2/retrieval-requests/{id} returns the open action request in pending_action_request:
document is a file Tavrn attached to the action request (for example, a provider invoice or no-records letter), or null. Its download_url expires after expires_in seconds; fetch the request for a fresh URL. When an action request opens or reopens, retrieval_request.action_required includes its ID. Fetch the request to read the message and any attachment; incremental polling also captures the update.
Text-only response
message is required (up to 10,000 characters). requester_email is optional and records who at your firm answered. The endpoint needs the retrievals:write scope.
Response with an attachment
Upload the file under the retrieval request’s case, then pass itsupload_id:
upload_id within one hour. Each upload_id can be used once.
How Tavrn handles your response
A rejected response (
400) leaves the action request open so you can retry. After a successful response the request leaves action_required (usually back to processing), and the timeline’s action_request shows status: "answered" with your response_text. Responding again after that returns 409, as does responding when there is no open action request.
Support messages
Send a question or instruction withPOST /v2/retrieval-requests/{retrieval_request_id}/messages. Requires retrievals:write and, for CMS-linked requests, support messaging enabled on the connection.
Messages and published replies are logged without changing retrieval status. Drafts and private notes are excluded.
message is required (maximum 10,000 characters). Upload attachments under the request’s case, then include attachment: { "upload_id": "..." }.
Identical submissions within 10 minutes return the existing conversation with deduplicated: true. Concurrent submissions return 409 (support_message_in_progress); retry shortly.
Success confirms submission, not completion of the requested work.