Send a Patient's Visit Summary
A patient has asked that a document you hold reach their referring provider: a visit summary, a lab result, a discharge note. Send that data via Direct Secure Message.
Three steps:
| Step | What you do | Endpoint |
|---|---|---|
| 1 | Contribute the patient and the document | POST /4_0_0/Bundle/$merge |
| 2 | Instruct b.well to transmit it over Direct | POST /v1/Task |
| 3 | Confirm it arrived | GET /v1/Task/{id} |
Step 1 is not optionalThe Task in step 2 references documents by the ids
$mergereturns, and b.well rejects a Task whose documents it cannot find.
Before you begin
b.well issues these to your organization during onboarding:
- OAuth client id and client secret, per environment
- Your organization slug, used in
meta.securityon every resource you contribute - Your Direct address, registered administratively with b.well
Your credentials arrive pre-scoped. You do not request or send OAuth scopes.
Direct addresses are provisioned, not self-serviceb.well verifies your
sender-direct-addressbelongs to a domain registered to your client before it will send; an unregistered address fails withsender-address-not-authorized. This happens during onboarding — not at integration time, and not as a FHIR resource you create.
| Environment | Base URL |
|---|---|
| Sandbox | https://api.client-sandbox.icanbwell.com |
| Production | https://api.icanbwell.com |
Begin in SandboxExamples below use the Sandbox base URL. Substitute your own values for
your-org-slug,https://your-org.example.com, and the placeholder credentials — all example data is fictional.
Authenticate
curl --request POST \
--url https://api.descope.com/oauth2/v1/apps/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data client_id=<your_client_id> \
--data client_secret=<your_client_secret> \
--data grant_type=client_credentialsUse the returned access_token as your Bearer token. Tokens last 600 seconds, so re-authenticate on a 401 rather than caching one for the life of a batch job.
Every request below also sends Content-Type: application/fhir+json, Accept: application/fhir+json, and an X-Request-Id UUID you generate per attempt.
Log that id. It is how b.well locates your request when you raise a support issue.
Step 1 — Contribute the patient and document
curl -X POST https://api.client-sandbox.icanbwell.com/4_0_0/Bundle/$merge \
-H "Content-Type: application/fhir+json" \
-H "Accept: application/fhir+json" \
-H "Authorization: Bearer <access_token>" \
-H "X-Request-Id: $(uuidgen)" \
-d '@bundle.json'One submission carries four resources: a Patient, a Person linked to it, a DocumentReference, and the Binary holding the file.
Rules that matter:
Bundle.typeiscollection.- Every resource carries
meta.sourceand ameta.securityblock withowner,access, andsourceAssigningAuthority, all set to your org slug. - The
Binaryholds the file inline as base64. TheDocumentReferencepoints at it by URL rather than embedding the bytes twice, and that URL uses the resolved environment base URL, with aBinaryid matching theBinaryin the same bundle. - Keep a submission under 20 MB total, including the base64. Split larger document sets.
Example request payload
{
"resourceType": "Bundle",
"type": "collection",
"entry": [
{
"resource": {
"resourceType": "Patient",
"id": "9f1c1c8e-3a4b-4c2f-9d3e-6a7b8c9d0e1f",
"meta": {
"source": "https://your-org.example.com",
"security": [
{ "system": "https://www.icanbwell.com/owner", "code": "your-org-slug" },
{ "system": "https://www.icanbwell.com/access", "code": "your-org-slug" },
{ "system": "https://www.icanbwell.com/sourceAssigningAuthority", "code": "your-org-slug" }
]
},
"identifier": [
{
"use": "usual",
"type": {
"coding": [
{ "system": "http://terminology.hl7.org/CodeSystem/v2-0203", "code": "MR", "display": "Medical record number" }
]
},
"system": "https://your-org.example.com/mrn",
"value": "MRN-0001842"
}
],
"active": true,
"name": [ { "use": "official", "family": "Doe", "given": ["Jane", "M"] } ],
"gender": "female",
"birthDate": "1964-01-01",
"address": [
{ "use": "home", "line": ["1200 Congress Ave"], "city": "Austin", "state": "TX", "postalCode": "78701", "country": "US" }
]
}
},
{
"resource": {
"resourceType": "Person",
"id": "2b7de4a1-5f60-4d18-8b0c-1e2f3a4b5c6d",
"meta": {
"source": "https://your-org.example.com",
"security": [
{ "system": "https://www.icanbwell.com/owner", "code": "your-org-slug" },
{ "system": "https://www.icanbwell.com/access", "code": "your-org-slug" },
{ "system": "https://www.icanbwell.com/sourceAssigningAuthority", "code": "your-org-slug" }
]
},
"identifier": [
{ "system": "https://your-org.example.com/person", "value": "PSN-77213" }
],
"active": true,
"name": [ { "use": "official", "family": "Doe", "given": ["Jane", "M"] } ],
"gender": "female",
"birthDate": "1964-01-01",
"link": [
{ "target": { "reference": "Patient/9f1c1c8e-3a4b-4c2f-9d3e-6a7b8c9d0e1f" } }
]
}
},
{
"resource": {
"resourceType": "DocumentReference",
"id": "c4d5e6f7-8a9b-4c0d-9e1f-2a3b4c5d6e7f",
"meta": {
"source": "https://your-org.example.com",
"security": [
{ "system": "https://www.icanbwell.com/owner", "code": "your-org-slug" },
{ "system": "https://www.icanbwell.com/access", "code": "your-org-slug" },
{ "system": "https://www.icanbwell.com/sourceAssigningAuthority", "code": "your-org-slug" }
]
},
"status": "current",
"docStatus": "final",
"type": {
"coding": [
{ "system": "http://loinc.org", "code": "34133-9", "display": "Summary of episode note" }
],
"text": "Visit summary"
},
"subject": { "reference": "Patient/9f1c1c8e-3a4b-4c2f-9d3e-6a7b8c9d0e1f" },
"date": "2026-08-10T18:04:00-04:00",
"content": [
{
"attachment": {
"contentType": "application/pdf",
"url": "https://api.client-sandbox.icanbwell.com/v1/Binary/d7df09d0-4538-4839-868f-20c6997cab38",
"title": "Visit summary 2026-08-10.pdf",
"creation": "2026-08-10T18:04:00-04:00"
}
}
]
}
},
{
"resource": {
"resourceType": "Binary",
"id": "d7df09d0-4538-4839-868f-20c6997cab38",
"meta": {
"source": "https://your-org.example.com",
"security": [
{ "system": "https://www.icanbwell.com/owner", "code": "your-org-slug" },
{ "system": "https://www.icanbwell.com/access", "code": "your-org-slug" },
{ "system": "https://www.icanbwell.com/sourceAssigningAuthority", "code": "your-org-slug" }
]
},
"contentType": "application/pdf",
"data": "JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC9UeXBlL0NhdGFsb2c+PgplbmRvYmoK"
}
}
]
}Capture the ids, and check every entry
200 OK returns one result per submitted resource.
Example $merge response
$merge response[
{ "resourceType": "Patient", "id": "9f1c1c8e-3a4b-4c2f-9d3e-6a7b8c9d0e1f", "uuid": "9f1c1c8e-3a4b-4c2f-9d3e-6a7b8c9d0e1f", "created": true, "updated": false, "sourceAssigningAuthority": "your-org-slug" },
{ "resourceType": "Person", "id": "2b7de4a1-5f60-4d18-8b0c-1e2f3a4b5c6d", "uuid": "2b7de4a1-5f60-4d18-8b0c-1e2f3a4b5c6d", "created": true, "updated": false, "sourceAssigningAuthority": "your-org-slug" },
{ "resourceType": "DocumentReference", "id": "c4d5e6f7-8a9b-4c0d-9e1f-2a3b4c5d6e7f", "uuid": "c4d5e6f7-8a9b-4c0d-9e1f-2a3b4c5d6e7f", "created": true, "updated": false, "sourceAssigningAuthority": "your-org-slug" },
{ "resourceType": "Binary", "id": "d7df09d0-4538-4839-868f-20c6997cab38", "uuid": "d7df09d0-4538-4839-868f-20c6997cab38", "created": true, "updated": false, "sourceAssigningAuthority": "your-org-slug" }
]Persist the Patient id and each DocumentReference id. Step 2 needs both.
A 200 does not mean every resource persistedA validation error on one entry does not fail the request; that entry comes back as an
OperationOutcomeinstead of a merge result. Iterate the array and treat anyOperationOutcomeas a failure for that resource. ADocumentReferencethat silently failed here resurfaces in step 2 asdocument-not-found, which is much harder to trace back.
Retrying is safeb.well matches on
resource.idplus your org slug and returns the sameuuid.created: false, updated: falsemeans the resource already existed and your payload was identical — so re-sending an unchanged bundle is a no-op.
Step 2 — Submit the Direct send Task
A Task with code send-direct-message asks b.well to transmit the documents to a named provider.
Prerequisites: the Patient and every DocumentReference exist and persisted; your sender-direct-address is registered; and you have Organization and Practitioner references for sender and recipient.
Addressing the recipient
Every Task uses one of two modes:
| Mode | You supply | To address |
|---|---|---|
| Directory | recipient-practitioner and recipient-organization | Resolved from the practitioner's role at that organization |
| Explicit | recipient-direct-address | Used exactly as given |
Addresses are bare strings with no mailto: prefix and no wrapping Endpoint resource. One recipient per Task; to reach several providers, submit several Tasks sharing a groupIdentifier.
Prefer Directory modeb.well confirms an explicit address is well-formed and that a trust path exists, but not that it belongs to the clinician you meant. One transposed character that resolves to a different real Direct address delivers the patient's records to the wrong provider, and Direct reports that as success. Treat operator-typed addresses as the highest-risk path in this workflow.
curl -X POST https://api.client-sandbox.icanbwell.com/v1/Task \
-H "Content-Type: application/fhir+json" \
-H "Accept: application/fhir+json" \
-H "Authorization: Bearer <access_token>" \
-H "X-Request-Id: $(uuidgen)" \
-d '@task.json'Example request payload
{
"resourceType": "Task",
"meta": {
"source": "https://your-org.example.com",
"security": [
{ "system": "https://www.icanbwell.com/owner", "code": "your-org-slug" },
{ "system": "https://www.icanbwell.com/access", "code": "your-org-slug" }
]
},
"identifier": [
{ "system": "https://your-org.example.com/tasks", "value": "TSK-004417" }
],
"groupIdentifier": {
"system": "https://your-org.example.com/referrals",
"value": "REF-2026-0881"
},
"status": "requested",
"intent": "order",
"code": {
"coding": [
{
"system": "https://fhir.icanbwell.com/CodeSystem/task-code",
"code": "send-direct-message",
"display": "Send documents via Direct secure messaging"
}
]
},
"for": { "reference": "Patient/9f1c1c8e-3a4b-4c2f-9d3e-6a7b8c9d0e1f" },
"authoredOn": "2026-08-11T14:35:00-04:00",
"requester": { "reference": "Organization/5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b" },
"reasonCode": {
"coding": [
{ "system": "http://terminology.hl7.org/CodeSystem/v3-ActReason", "code": "PATRQT", "display": "patient requested" }
],
"text": "Patient asked that records be sent to her referring provider."
},
"input": [
{
"type": { "coding": [ { "system": "https://fhir.icanbwell.com/CodeSystem/task-input-type", "code": "sender-organization" } ] },
"valueReference": { "reference": "Organization/5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b" }
},
{
"type": { "coding": [ { "system": "https://fhir.icanbwell.com/CodeSystem/task-input-type", "code": "sender-direct-address" } ] },
"valueString": "[email protected]"
},
{
"type": { "coding": [ { "system": "https://fhir.icanbwell.com/CodeSystem/task-input-type", "code": "recipient-practitioner" } ] },
"valueReference": { "reference": "Practitioner/4e5f6a7b-8c9d-4e0f-9a1b-2c3d4e5f6a7b" }
},
{
"type": { "coding": [ { "system": "https://fhir.icanbwell.com/CodeSystem/task-input-type", "code": "recipient-organization" } ] },
"valueReference": { "reference": "Organization/8c1d2e3f-4a5b-4c6d-8e9f-0a1b2c3d4e5f" }
},
{
"type": { "coding": [ { "system": "https://fhir.icanbwell.com/CodeSystem/task-input-type", "code": "document" } ] },
"valueReference": { "reference": "DocumentReference/c4d5e6f7-8a9b-4c0d-9e1f-2a3b4c5d6e7f" }
},
{
"type": { "coding": [ { "system": "https://fhir.icanbwell.com/CodeSystem/task-input-type", "code": "message-subject" } ] },
"valueString": "Records for referral REF-2026-0881"
},
{
"type": { "coding": [ { "system": "https://fhir.icanbwell.com/CodeSystem/task-input-type", "code": "message-body" } ] },
"valueString": "Attached is the visit summary from the 2026-08-10 encounter, sent at the patient's request."
}
]
}Repeat the document input once per DocumentReference. All documents on one Task go out as a single Direct message.
Optional but worth setting: sender-practitioner populates the message display name, reasonReference points at a Consent where written authorization backs the disclosure, and restriction.period.end sets a delivery deadline after which the Task fails rather than staying in flight.
No PHI in the subject lineDirect encrypts message content, but subject lines are widely logged by intermediate systems and surfaced in notification emails. Reference the patient by an internal id or referral number, as above, and never by name or date of birth.
201 Created means the Task was accepted, not that the message was sentSave the returned
id. Validation failures that depend on your inputs like unauthorized sender address, malformed recipient, and missing document, all surface here. Failures that depend on address resolution and trust surface later, in step 3.
Step 3 — Confirm it arrived
curl https://api.client-sandbox.icanbwell.com/v1/Task/3d9f5a71-2c84-4e16-9b03-7a8c9d0e1f2a \
-H "Accept: application/fhir+json" \
-H "Authorization: Bearer <access_token>"Task.status is the FHIR lifecycle; Task.businessStatus is the Direct-specific detail within it. The pair you are waiting for is:
"status": "completed", "businessStatus": "mdn-dispatched"That means delivered, and it is terminal. Poll no more often than once per minute, back off exponentially, and stop at any terminal state : completed, failed, rejected, or cancelled.
mdn-processedis not deliveryIt means a HISP accepted custody and verified trust; the records can still bounce before reaching the recipient's system. If your workflow tells a care coordinator "records sent," gate that on
mdn-dispatched.
On success, Task.output carries the evidence: most usefully direct-message-id, the RFC 5322 Message-ID. Log it; it is the correlation key for any support request about that send.
On failure, Task.output.failure-reason classifies why, and tells you whether b.well will retry. A Task at in-progress with a rising attempt-count is being worked on. Do not submit a duplicate. Create a new Task only once the existing one is terminal and the failure is something you can fix: a corrected address, a document that now exists, a narrowed recipient. Use a new identifier, reuse the groupIdentifier.
Every retry puts another copy of the patient's records in flightConfirm the address before resending after a
notification-timeout, which otherwise tends to time out again for the same reason.
Errors
| Status | What to do |
|---|---|
400 / 422 | Malformed or invalid FHIR. Do not retry without changing the payload. |
401 | Token expired. They last 600 seconds. Re-authenticate and retry. |
403 | Your credentials are not authorized for this operation. Contact b.well; retrying will not help. |
200 on $merge | Check every entry. See Step 1. |
Updated 20 days ago
