Skip to main content

Report Generation

To generate reports there's two options: via the API or via Tiep's UI (using a webhook).

Option 1: Report generation with API

Run Tiep from your HIS

Use this path when you want to keep every interaction inside your Hospital Information System without opening the Tiep UI.

  1. Capture the encounter audio. Record the consultation locally in your HIS in a supported format (audio/wav).
  2. Call the transcription endpoint. Send the recording to POST https://api.tiep.ai/v1/transcribe-and-generate with the facility API key in the X-API-Key header.
  3. Add context metadata. Provide the patient information, doctor identifier, and any additional tags in the JSON payload so the generated report is scoped correctly.
{
"doctor_id": "382",
"report_template_id": 3,
"patient": {
"resourceType": "Patient",
"identifier": [
{
"value": "123456"
}
],
"name": [
{
"use": "official",
"text": "John Smith"
}
]
}
}
  1. Persist the response. Store the returned report, conversation transcript, and structured data in your clinical system.

Sample request:

curl -X POST "https://api.tiep.ai/v1/transcribe-and-generate" \
-H "X-API-Key: $FACILITY_API_KEY" \
-F "audio=@/path/to/consultation.wav" \
-F 'payload={
"doctor_id": "1",
"report_template_id": 3,
"patient": {
"identifier": "123456",
...
"name": "John Smith"
},
};type=application/json'

Each successful call returns the medical report plus the same HL7 FHIR bundle described in the Payload format guide. Store the identifiers you receive so you can reconcile future webhook deliveries or audit activity later.

Option 2: Report generation with webhook and Tiep's UI

Tiep communicates with your Hospital Information System (HIS) through a webhook endpoint that you expose. Whenever a physician saves a consultation, Tiep issues an HTTP POST request against that URL with the structured consultation payload. Your HIS can then persist or act on the payload automatically (store the consultation, schedule a follow-up, order imaging, and so on).

Steps

1. Sign in and create your first facility

Start by reaching out to our team at [email protected] so we can enable your tenant. Once you are approved, the designated admin receives a sign in with email link. Use that link to access the Tiep Platform and follow either the UI-based facility flow or the API-based facility flow. After the facility exists, generate a facility API key so you can continue with the integration steps below.

tip

Keep facility API keys in your secret manager and rotate them regularly. Each facility can store up to three active keys.

2. Create doctors

Each physician must be associated with an active user before they can work with Tiep. Create every doctor you want to onboard by issuing a POST https://api.tiep.ai/v1/doctors request signed with the facility API key in the X-API-Key header.

X-API-Key: <FACILITY_API_KEY>

For example, to register Dr. Juan Garcia you would send:

{
"id": "1",
"name": "Juan Garcia",
"specialties": ["ORTHOPEDICS", "SPORTS_MEDICINE", "CARDIOLOGY"]
}

The id is the HIS identifier for the doctor and is required so that activity can be reconciled later. Use an alphanumeric string—if your HIS uses numeric IDs, convert them to strings before creating the record. The specialties array grants access to the corresponding template packs. Below is the complete list of specialties currently available:

SpecialtyTemplate
ALLERGYAllergy
ANESTHESIOLOGYPreoperative
CARDIOLOGYCardiology
GASTROENTEROLOGYDigestive
GYNECOLOGYGynecology
HEMATOLOGYHematology
INTERNAL_MEDICINEInternal medicine
MAXILLOFACIALMaxillofacial
NEPHROLOGYNephrology
NEUROLOGYNeurology
ONCOLOGYBreast cancer
OPHTHALMOLOGYOphthalmology
ORTHOPEDICSSpine
ORTHOPEDICSShoulder
ORTHOPEDICSHand
ORTHOPEDICSFoot
ORTHOPEDICSKnee
ORTHOPEDICSHip
ORTHOPEDICSElbow
OTOLARYNGOLOGYOtolaryngology
PSYCHIATRYPsychiatry
PULMONOLOGYPulmonology
RHEUMATOLOGYRheumatology
SPORTS_MEDICINESports medicine
VASCULARVascular

3. Configure the webhook

In the platform, navigate to Settings → Integration and provide the HTTPS endpoint that will receive webhook calls. Define a webhook secret (16 characters minimum) while you are there—Tiep uses it to sign every payload.

What is the webhook secret?

The secret lets you verify that inbound requests originated from Tiep and that no one tampered with them in transit. Use the same secret to recompute the hash when you receive an event. See Step 5 for a verification example.

Doctors access the Tiep UI through a link generated by your HIS. Send a POST https://api.tiep.ai/v1/auth/generate-token request containing the doctor's internal identifier:

{
"doctor_id": "1"
}

You will receive a short-lived token that allows the physician to authenticate into Tiep (the token expires after 10 minutes):

{
"token": "qKaIW2jUWEFT841tP_vMYoswTAXiejtPgqf3sHQ90iY"
}

The final launch URL combines the token with a context query parameter that contains patient metadata encoded as URL-safe Base64 JSON. The JSON payload must include a patient key. You can add any additional metadata you need; Tiep will echo it back inside the webhook payload.

{
"patient": {
"resourceType": "Patient",
"identifier": [
{
"value": "123456"
}
],
"name": [
{
"use": "official",
"text": "John Smith"
}
]
},
"is_first_visit": true,
"consultation_id": 123,
"any_other_key": "more metadata information"
}

Given the example above, the resulting link would look like:

https://consulta.tiep.ai/?token=qKaIW2jUWEFT841tP_vMYoswTAXiejtPgqf3sHQ90iY&context=eyJwYXRpZW50IjogeyJyZXNvdXJjZVR5cGUiOiAiUGF0aWVudCIsICJpZGVudGlmaWVyIjogW3sidmFsdWUiOiAiMTIzNDU2In1dLCAibmFtZSI6IFt7InVzZSI6ICJvZmZpY2lhbCIsICJ0ZXh0IjogIkpvaG4gU21pdGgifV19LCAiaXNfZmlyc3RfdmlzaXQiOiB0cnVlLCAiY29uc3VsdGF0aW9uX2lkIjogMTIzLCAiYW55X290aGVyX2tleSI6ICJtb3JlIG1ldGFkYXRhIGluZm9ybWF0aW9uIn0=

Tiep stores any extra data under the context key within the resulting Appointment resource. See the Payload format guide for details.

danger

Consultations cannot be saved without context—always include the context parameter in the launch URL so the patient can be identified.

Example

Here is how you could wire those pieces together in Python (replace API_KEY with the facility API key you generated earlier):

import json
from urllib.parse import urlencode
from base64 import urlsafe_b64encode

import requests


CONSULTATIONS_URL = "https://consulta.tiep.ai"
API_KEY = "2f32c3d709ff7db4ab43143ea477919d"
API_URL = "https://api.tiep.ai/v1"


def create_doctor(uid, name):
res = requests.post(
f"{API_URL}/doctors",
json={"id": str(uid), "name": name, "specialty": "Traumatology"},
headers={"X-API-Key": API_KEY},
)
if res.status_code == 201:
print("Doctor created!")


def get_ephemeral_token(doctor_id: str):
res = requests.post(
f"{API_URL}/auth/generate-token",
json={"doctor_id": doctor_id},
headers={"X-API-Key": API_KEY},
)
res.raise_for_status()
return res.json()


def generate_consultation_url(doctor_id: str, context):
query_params = {
"token": get_ephemeral_token(doctor_id)["token"],
"context": urlsafe_b64encode(json.dumps(context).encode()).decode(),
}
return f"{CONSULTATIONS_URL}?{urlencode(query_params)}"

5. Receive the reports

Tiep issues a POST request to your webhook every time a consultation report is finalized. We retry the delivery once and stop if your endpoint does not return a 200 status code.

Each payload is signed with the webhook secret using an HMAC SHA-256 digest and sent in the X-Signature-256 header. The first thing your handler should do is recompute the signature and compare it against the provided value.

Keep the following in mind when validating webhook payloads:

  • Tiep uses an HMAC hexadecimal digest.
  • The signature always begins with sha256=.
  • The digest is calculated with your webhook secret and the raw request body.
  • If your language or framework enforces an encoding, ensure the raw body is treated as UTF-8.
  • Avoid plain == comparisons; prefer constant-time checks such as hmac.compare_digest or crypto.timingSafeEqual.
Example
import hmac
import json
from hashlib import sha256

from django.http import JsonResponse
from django.utils.decorators import method_decorator
from django.views import View
from django.views.decorators.csrf import csrf_exempt

from his.models import Consultation


@method_decorator(csrf_exempt, name="dispatch")
class ConsultationWebhookView(View):
TOKEN = "MY-SECRET"

def post(self, request, *args, **kwargs):
received_signature = request.headers.get("x-signature-256")
expected_signature = f"sha256={hmac.new(self.TOKEN.encode(), msg=request.body, digestmod=sha256).hexdigest()}"
is_valid = hmac.compare_digest(received_signature, expected_signature)
if is_valid:
data = json.loads(request.body)
Consultation.objects.create(data=data)
return JsonResponse(
{"status": "success", "message": "Consultation received"},
status=200,
)
else:
return JsonResponse({"status": "error", "message": "Invalid signature"}, status=400)