Bulk Import Appointments

Bulk Import Appointments

POST /api/appointment_schedule/bulk

Import appointment schedules. The endpoint accepts either a JSON array sent directly as the request body or a file upload (Excel .xlsx, CSV .csv, or JSON .json). Supports synchronous and background (Celery) processing modes — both run the same import logic and return the same result shape.

Processing Mode

Both modes share the same import business logic; only the result delivery differs.

Mode How to select Response Use when
background (default) Omit the parameter 202 + background_task_uuid to poll Large imports or when you don't need the result immediately
sync JSON: ?processing_mode=sync — File: form field processing_mode=sync 200 + full result inline Small imports when you want the result in the same request
Tip: In sync mode you get the result directly and can skip the Background Processing endpoints.

Request Body — JSON

Send a JSON array of objects directly as the request body (Content-Type: application/json). processing_mode is passed as a query parameter in this mode:

Parameter Type Required Description
tag_name string Yes QR code tag name
tag_number string Yes QR code tag number
start_date_time string Yes Appointment start date/time (YYYY-MM-DD HH:mm)
location string Yes Full address of the appointment
duration integer No Duration in minutes (Default 60 mins)
service string No Service of the appointment (Either service or service code is required)
service_code string No Service code of the appointment (Either service or service code is required)
timezone_name string No Timezone name (e.g. Australia/Melbourne)
job_reference_id string No External job/reference identifier
organization_uuid string Yes UUID of the organization

Example — JSON

json
[
  {
    "tag_name": "dest15",
    "tag_number": "Sync-15",
    "start_date_time": "2026-08-20T10:00:00",
    "location": "78 Garden Grove Parade, 3 unit, Adamstown Heights, New South Wales 2289, Australia",
    "duration": 20,
    "service": "Consultation",
    "timezone_name": "Australia/Melbourne",
    "job_reference_id": "JOB-0001",
    "organization_uuid": "Po5fQfUGec5ucKFeMDes24"
  }
]

Request Body — File

Upload an Excel, CSV, or JSON file (multipart/form-data):

Parameter Type Required Description
file file Yes Excel (.xlsx), CSV (.csv), or JSON (.json) file containing appointment data
organization_uuid string Yes UUID of the organization to import appointments for
org_identifier string No Slug identifying the import handler (e.g. monash_health, default)
processing_mode string No Processing mode: background (Celery, default) or sync (blocking)

Example — File

bash
curl -X POST /api/appointment_schedule/bulk \
  -F "file=@appointments.xlsx" \
  -F "organization_uuid=XYZ789UVW123RST456MNOP" \
  -F "processing_mode=background"

See Errors & Rate Limits for the common error contract used across the API.

Error Codes

Status Meaning
200 Import complete (sync mode)
202 Processing started (background mode)
400 Bad Request — missing file/body or invalid parameters
401 Unauthorized
403 Permission denied
500 Internal Server Error

Example Request — JSON

curl
curl -X POST "http://staging.didyougo.com.au/api/appointment_schedule/bulk?processing_mode=sync" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your_api_key:your_api_secret" \
  -d '[
  {
    "tag_name": "dest15",
    "tag_number": "Sync-15",
    "start_date_time": "2026-08-20T10:00:00",
    "location": "78 Garden Grove Parade, 3 unit, Adamstown Heights, New South Wales 2289, Australia",
    "duration": 20,
    "service": "Consultation",
    "timezone_name": "Australia/Melbourne",
    "job_reference_id": "JOB-0001",
    "organization_uuid": "Po5fQfUGec5ucKFeMDes24"
  }
]'

Try It

Try it

Requests are sent without cookies — you must provide a valid Bearer <api_key>:<api_secret> header.

API Response
Click the Send API Request button above and see the response here!

Example Request — File

curl
curl -X POST http://staging.didyougo.com.au/api/appointment_schedule/bulk \
  -H "Authorization: Bearer your_api_key:your_api_secret" \
  -F "file=@appointments.xlsx" \
  -F "organization_uuid=org-uuid-here" \
  -F "processing_mode=background"

Try It

Try it

Requests are sent without cookies — you must provide a valid Bearer <api_key>:<api_secret> header.

API Response
Click the Send API Request button above and see the response here!

Example Response (Background)

json
{
  "message": "Bulk import started in background (Celery).",
  "task_id": "celery-task-id-here",
  "background_task_uuid": "DEF789GHI012JKL345MNOP"
}

Poll /api/background-tasks/uuid/{background_task_uuid} until the status is COMPLETED or FAILED. See Background Processing for the full flow.

Example Response (Sync)

json
{
  "appointment_schedules_upserted": [
    {
      "organization_uuid": "Po5fQfUGec5ucKFeMDes24",
      "qr_code_uuid": "9kp4uYEhERwDEi6VDWXTYw",
      "qr_code_tag_uuid": "nTCCBKWHoTMGcJvMP7QaNM",
      "service": "Consultation",
      "appointment_date": "2026-08-20",
      "start_date_time": "2026-08-20T10:00:00+10:00",
      "end_date_time": "2026-08-20T10:30:00+10:00",
      "duration": 30,
      "all_day": false,
      "no_date_time_provided": false,
      "job_reference_id": "JOB-0001",
      "type": "SERVICE"
    }
  ],
  "excluded_appointments": []
}

excluded_appointments contains one entry per rejected row with its index, data, and error_message.