heyvisa

Your First Report

A report ties an applicant profile to a set of uploaded documents and returns a risk-scored, prioritised set of recommendations. This page walks through a complete end-to-end request, with the exact JSON you will see in production.

Before you start

  1. You have a live or test API key (see Authentication).
  2. You have uploaded any supporting documents via the Documents API and recorded their doc_… identifiers.
  3. You have a publicly reachable webhook URL if you want to avoid polling.

1. Build the payload

The applicant block is required; everything else is optional but improves scoring quality. Document IDs are attached by reference rather than re-uploaded.

json
{
  "applicant": {
    "full_name": "Ayşe Yılmaz",
    "country": "TR",
    "destination": "DE",
    "purpose": "tourism",
    "travel_dates": {
      "from": "2026-09-12",
      "to": "2026-09-22"
    },
    "previous_travel": ["FR", "IT", "GB"],
    "employment_status": "employed",
    "monthly_income_usd": 2400
  },
  "documents": [
    "doc_01HXYZbankstmt",
    "doc_01HXYZpassport",
    "doc_01HXYZemployment"
  ],
  "webhook_url": "https://app.example.com/heyvisa/hooks"
}

Required fields

applicant.country (ISO-3166-1 alpha-2), applicant.destination (same format), and applicant.purpose (one of tourism, study, work, business, transit).

2. Submit the request

bash
curl -X POST https://api.heyvisa.com/v1/reports \
  -H "Authorization: Bearer $HEYVISA_API_KEY" \
  -H "Content-Type: application/json" \
  -d @report.json

3. Immediate response

The API responds within ~100 ms with the queued report. Persist theid so you can correlate the eventual completion event.

json
{
  "id": "rep_01HXYZ8K7M3N5P2Q4R6S8T0V2W",
  "object": "report",
  "status": "queued",
  "created_at": "2026-06-11T09:21:14Z",
  "applicant": {
    "country": "TR",
    "destination": "DE",
    "purpose": "tourism"
  },
  "documents": [
    "doc_01HXYZbankstmt",
    "doc_01HXYZpassport",
    "doc_01HXYZemployment"
  ]
}

4. Receive the completed report

When the analysis pipeline finishes, the report transitions to completed (or failed on a hard error). If a webhook URL was provided we POST the payload to it; otherwise fetch the report by ID.

json
{
  "id": "rep_01HXYZ8K7M3N5P2Q4R6S8T0V2W",
  "object": "report",
  "status": "completed",
  "created_at": "2026-06-11T09:21:14Z",
  "completed_at": "2026-06-11T09:21:47Z",
  "risk_score": 68,
  "risk_band": "medium",
  "signals": {
    "documents": { "score": 74, "missing": [] },
    "finances":  { "score": 61, "notes": ["Income below median for destination."] },
    "intent":    { "score": 72, "notes": ["Reasonable trip length, clear itinerary."] }
  },
  "recommendations": [
    {
      "id": "rec_increase_funds_proof",
      "priority": "high",
      "summary": "Add a savings account statement covering the last 3 months.",
      "impact": "+8 expected score points"
    },
    {
      "id": "rec_employer_letter",
      "priority": "medium",
      "summary": "Attach an employer letter confirming leave dates."
    }
  ]
}
You shipped your first report
From here, explore how the risk score is calculated and how to wire webhooks for production.