Auto Scheduler
HargaArea ujiAlurBlogPertanyaan yang Sering DiajukanDokumentasi API
Masuk

Auto Scheduler

Layanan cloud untuk optimasi jadwal shift dan penjadwalan—adil, mematuhi kendala operasional, dan mudah dioperasikan.

Ketentuan Layanan|Kebijakan Privasi|Pengungkapan Hukum

Solver (pengelola)

Di halaman ini

RingkasanCakupanLangganan & penagihanAutentikasiSalin untuk LLMEndpointCara memanggil (mulai cepat)MCP (agen)API baca (GET)API tulis (PATCH / POST / PUT / DELETE)Webhook penyelesaianHeaderBatas & defaultKunci root yang diizinkanRingkasan body permintaanTabel referensi cepatReferensi field (nilai yang diizinkan)apiVersiontimeZonescheduleStartDate / scheduleEndDatetimeRangeStart / timeRangeEndslotGranularityMinutesrequirementsByCellrequiredRolesByCellstaffavailableCellsstaff[].schedulingRoleIds / Soft prefer-avoidHukum kerja & flag berbayar (default server)SanitasiRespons suksesDaftar kode errorContoh JSONBacaan lanjutan

Auto Scheduler

API berbayar · Langganan

Referensi API pengembang

Integrasikan API produksi untuk pengiriman jadwal dengan kunci API yang terikat ke langganan berbayar Anda. Default penyewa dapat disimpan dengan PATCH /v1/schedule-defaults; harian mingguan per staf dibaca atau diganti penuh dengan GET/PUT /v1/staff/{staffId}/weekly-shift-wish. Penagihan mengikuti paket dan kontrak Anda (bukan bayar per panggilan API). Halaman ini mendokumentasikan hak, aturan validasi, dan kode error — gunakan bilah sisi untuk melompat ke setiap field.

Cakupan dokumentasi ini

Halaman ini mendokumentasikan API REST produk untuk integrasi eksternal.

Webhook penyelesaian hasil jadwal adalah notifikasi HTTPS keluar yang dikonfigurasi di manajemen API (bukan CRUD REST). Lihat Completion webhooks di halaman ini.

Rute browser internal (mis. callback pembayaran atau analitik) bukan pengganti API produk ini. Untuk sistem eksternal, gunakan /v1/* dan webhook penyelesaian.

Langganan & akses

API HTTP ini merupakan bagian produk berbayar: akses memerlukan perjanjian komersial aktif dan kunci diterbitkan ke organisasi Anda setelah onboarding.

Penagihan berdasarkan langganan dan kontrak. Untuk paket berbayar, biaya biasanya mengikuti halaman harga (mis. per staf terdaftar per bulan).

Batas playground / tingkat gratis tidak berlaku untuk kunci API berbayar. Batas efektif seperti rentang jadwal, jumlah staf, dan granularitas 15 menit ditentukan oleh hak berbayar Anda. Lihat Batas & default di halaman ini.

Autentikasi

Permintaan harus menyertakan kunci API yang valid yang diterbitkan untuk langganan berbayar Anda. Buat, putar, dan cabut kunci dari area akun setelah masuk.

Kirim kunci di header x-api-key. Kunci terikat ke organisasi Anda untuk identifikasi penyewa dan batas akses berdasarkan paket. Operasi di luar scopes mengembalikan 403 (API_KEY_SCOPE_DENIED). Kunci lama tanpa atribut scopes tetap mengizinkan semua operasi.

Kelola kunci: Manajemen API

Salin untuk LLM

Tempel blok di bawah ke asisten obrolan saat Anda ingin bantuan memanggil API produk ini tanpa mengonfigurasi MCP.

Merangkum base URL, autentikasi, operasi utama, dan peringatan tulis. Tidak pernah menyertakan kunci API nyata.

Untuk panggilan API nyata dari agen, konfigurasikan MCP (agen) daripada hanya mengandalkan teks tempel ini.

Konteks untuk ditempel

Auto Scheduler — Public API context for LLM assistants

Use this when helping a developer call the Auto Scheduler paid product REST API (/v1/*). Prefer configuring Tools MCP when available; this paste is for chat without MCP.

Base URL
- https://api.autoschedulers.com
- Paths are under /v1/*. Do not confuse this with the marketing website origin.

Authentication
- Every request needs header: x-api-key: <API_KEY>
- Never paste a real API key into chat logs or this prompt; ask the user to supply it via environment or a secret store.
- Keys are created in the product under Account → API management.
- JSON writes: Content-Type: application/json

Read endpoints
- GET /v1/schedule-results?limit=10
- GET /v1/schedule-results/{conditionId}
- GET /v1/schedule-conditions
- GET /v1/staff
- GET /v1/staff/{staffId}
- GET /v1/schedule-defaults
- GET /v1/schedule-results/{conditionId}/emergency-shift-context

Write endpoints (confirm with the user before calling)
- POST /v1/schedule — starts a job; may incur charges; max 14 calendar days
- PATCH /v1/schedule-defaults — tenant-wide
- POST /v1/staff
- PATCH /v1/staff/{staffId}
- PUT /v1/staff/{staffId}/weekly-shift-wish — full replace
- POST /v1/schedule-results/{conditionId}/emergency-shift — paid
- POST /v1/schedule-results/{conditionId}/confirm-assignments
- DELETE /v1/schedule-conditions/{conditionId}
- PUT /v1/schedule-actual/{conditionId} — full replace

Minimal curl (read)
curl -sS -H "x-api-key: YOUR_API_KEY" "https://api.autoschedulers.com/v1/staff"
curl -sS -H "x-api-key: YOUR_API_KEY" "https://api.autoschedulers.com/v1/schedule-results?limit=10"

Contract notes
- Schedule submit body needs a supported apiVersion and valid JSON fields — see api-docs Field reference or Docs MCP Resources; do not invent fields.
- planningHorizon on defaults is only week or two_weeks (month_attendance is rejected).
- Outbound completion webhooks are HMAC-signed HTTPS callbacks configured in API management (not REST CRUD).

Safety
- Write endpoints change tenant data. Confirm destructive or irreversible actions with the user before calling them.
- Prefer read/list first when exploring an unfamiliar tenant.

Endpoint

Kirim kondisi jadwal sebagai JSON. Ini adalah permukaan integrasi berbayar; URL dasar pasti diberikan per lingkungan setelah akses API disediakan.

URL dasar

Host API REST publik (/v1/*), bukan URL situs browser. Setel AUTO_SCHEDULER_PUBLIC_API_BASE_URL (MCP) dan BASE_URL (curl) ke nilai ini.

AUTO_SCHEDULER_PUBLIC_API_BASE_URL — URL dasar yang dikonfigurasi untuk lingkungan dokumentasi ini. Gunakan nilai yang sama di MCP dan curl.

AUTO_SCHEDULER_PUBLIC_API_BASE_URL=https://api.autoschedulers.com
https://api.autoschedulers.com
POST https://api.autoschedulers.com/v1/schedule

Gunakan URL dasar yang diberikan saat akses API disediakan atau oleh kontak operasi Anda.

Cara memanggil (mulai cepat)

Ganti **BASE_URL** dengan URL dasar API (awalan jalur) yang diberikan saat akses Anda disediakan.

Kirim kunci API di header **x-api-key**. Organisasi (penyewa) Anda diidentifikasi dari kunci — Anda tidak perlu mengirim ID penyewa terpisah di query string.

Fitur berbayar (detail ketenagakerjaan, beberapa default jadwal) memerlukan langganan berbayar yang aktif. Anda dapat menerima **503** (mis. kode **STRIPE_NOT_CONFIGURED**) bila penagihan belum dikonfigurasi. Profil perusahaan, log audit, dan pengelolaan pengguna (akun) dilakukan di aplikasi web dan bukan bagian dari API publik.

Contoh curl (bash / macOS / Linux / WSL)

Windows PowerShell: `\` di akhir baris **bukan** kelanjutan baris. Tulis satu baris, atau akhiri setiap baris dengan backtick (`) untuk melanjutkan.

curl -sS -D - \
  -H "x-api-key: YOUR_API_KEY" \
  "https://api.autoschedulers.com/v1/schedule-results?limit=10"

curl -sS -D - \
  -H "x-api-key: YOUR_API_KEY" \
  "https://api.autoschedulers.com/v1/staff"

MCP (agen)

Anda dapat memanggil API REST produk yang sama dari agen seperti Cursor, Claude, Gemini, dan GPT melalui MCP. Operasinya cocok dengan permukaan /v1 di halaman ini.

Server MCP bawaan memakai stdio lokal. Tambahkan command / args / env ke setiap file konfigurasi klien. Buat kunci di Manajemen API (jangan commit atau tempel ke chat publik).

Hanya untuk dokumentasi, MCP Resources tidak perlu login atau kunci API (mcp/api-docs). Halaman ini (/{locale}/api-docs) juga dapat dilihat tanpa masuk; membuat kunci tetap memerlukan Akun → Manajemen API.

Jalur tercepat (disarankan)

  1. Create an API key in Account → API management (never paste the real key into chat).
  2. In the repo: cd mcp/public-api && npm install && npm run build (also mcp/api-docs if you want documentation Resources).
  3. Copy the env snippet below and the Cursor mcp.json under Client-specific setup; replace paths and YOUR_* placeholders.
  4. Restart the client and confirm Tools (list_staff, …) appear. Prefer read tools before any write.

Opsi mana yang dipakai

  • Tools MCP (public-api)

    Live /v1 calls with your API key. Use this when the agent should actually list staff, submit schedules, etc.

  • Docs MCP (api-docs Resources)

    Contract markdown only—no API key. Use when the agent needs field rules or request-body shape.

  • Copy for LLM (this page)

    Orientation text for chat assistants without MCP. Not enough alone for correct request bodies—pair with MCP or the sections below.

Variabel lingkungan wajib (Tools MCP)

  • AUTO_SCHEDULER_PUBLIC_API_BASE_URL

    URL dasar API REST publik (/v1/*)—bukan domain situs. Gunakan host API yang diberikan (slash akhir opsional)

  • AUTO_SCHEDULER_API_KEY

    Kunci dari Manajemen API (jangan commit atau posting publik)

VariabelDeskripsi
AUTO_SCHEDULER_PUBLIC_API_BASE_URLURL dasar API REST publik (/v1/*)—bukan domain situs. Gunakan host API yang diberikan (slash akhir opsional)
AUTO_SCHEDULER_API_KEYKunci dari Manajemen API (jangan commit atau posting publik)

Cuplikan env (salin)

AUTO_SCHEDULER_PUBLIC_API_BASE_URL=https://api.autoschedulers.com
AUTO_SCHEDULER_API_KEY=YOUR_API_KEY

Persiapan bersama

  1. Buat kunci API di Manajemen API (hanya Tools MCP; tidak diperlukan untuk MCP docs)
  2. Di repo jalankan cd mcp/public-api → npm install && npm run build (dan mcp/api-docs jika ingin Resources)
  3. Ikuti langkah khusus klien di bawah dan sesuaikan path serta env untuk mesin Anda
  4. Mulai ulang klien (atau sambungkan ulang MCP) dan pastikan tools / resources muncul

Pengaturan khusus klien

Bentuk JSON hampir sama di mana-mana. Yang berbeda adalah lokasi file konfigurasi—dan bahwa ChatGPT (GPT) tidak menjalankan server stdio lokal.

Cursor

mcp.json pengguna (mis. Windows %USERPROFILE%\.cursor\mcp.json). Juga dapat diedit lewat Cursor Settings → MCP.

  1. Tambahkan cuplikan di bawah ke mcpServers (pertahankan server yang ada)
  2. Ganti path absolut dan YOUR_BASE_URL / YOUR_API_KEY
  3. Mulai ulang Cursor dan pastikan Tools seperti list_staff serta Resources dari api-docs

Di Windows escape backslash sebagai \\ di JSON. Di macOS / Linux gunakan path dengan slash.

{
  "mcpServers": {
    "auto-scheduler-public-api": {
      "command": "node",
      "args": [
        "C:\\path\\to\\auto-scheduler\\mcp\\public-api\\dist\\index.js"
      ],
      "env": {
        "AUTO_SCHEDULER_PUBLIC_API_BASE_URL": "https://api.autoschedulers.com",
        "AUTO_SCHEDULER_API_KEY": "YOUR_API_KEY"
      }
    },
    "auto-scheduler-api-docs": {
      "command": "node",
      "args": [
        "C:\\path\\to\\auto-scheduler\\mcp\\api-docs\\dist\\index.js"
      ]
    }
  }
}

public-api mengekspos Tools (perlu kunci API). api-docs mengekspos Resources (tanpa kunci).

Claude (Desktop)

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json / Windows: %APPDATA%\Claude\claude_desktop_config.json (Settings → Developer → Edit Config)

  1. Tambahkan cuplikan di bawah ke mcpServers di claude_desktop_config.json
  2. Sesuaikan path absolut dan env untuk mesin Anda
  3. Keluar sepenuhnya lalu mulai ulang Claude Desktop, lalu periksa Connectors / tools

Format mcpServers sama seperti Cursor. Ikuti alur Anthropic "Connect to local MCP servers".

{
  "mcpServers": {
    "auto-scheduler-public-api": {
      "command": "node",
      "args": [
        "C:\\path\\to\\auto-scheduler\\mcp\\public-api\\dist\\index.js"
      ],
      "env": {
        "AUTO_SCHEDULER_PUBLIC_API_BASE_URL": "https://api.autoschedulers.com",
        "AUTO_SCHEDULER_API_KEY": "YOUR_API_KEY"
      }
    },
    "auto-scheduler-api-docs": {
      "command": "node",
      "args": [
        "C:\\path\\to\\auto-scheduler\\mcp\\api-docs\\dist\\index.js"
      ]
    }
  }
}

Dengan Claude Code Anda juga dapat mendaftar lewat .mcp.json proyek atau claude mcp add.

Gemini (CLI)

Pengguna: ~/.gemini/settings.json / Proyek: .gemini/settings.json (proyek menang jika keduanya ada)

  1. Tambahkan cuplikan di mcpServers (atau gunakan gemini mcp add)
  2. Utamakan nama server ber-hyphen (batasan Gemini CLI)
  3. Jalankan CLI dan verifikasi dengan /mcp (koneksi + tools)

command / args / env cocok dengan Cursor dan Claude. Bidang opsional: timeout, trust: false.

{
  "mcpServers": {
    "auto-scheduler-public-api": {
      "command": "node",
      "args": [
        "C:\\path\\to\\auto-scheduler\\mcp\\public-api\\dist\\index.js"
      ],
      "env": {
        "AUTO_SCHEDULER_PUBLIC_API_BASE_URL": "https://api.autoschedulers.com",
        "AUTO_SCHEDULER_API_KEY": "YOUR_API_KEY"
      }
    },
    "auto-scheduler-api-docs": {
      "command": "node",
      "args": [
        "C:\\path\\to\\auto-scheduler\\mcp\\api-docs\\dist\\index.js"
      ]
    }
  }
}

Konektor konsol cloud Gemini menargetkan MCP jarak jauh. Gunakan Gemini CLI untuk stdio lokal.

GPT (ChatGPT / OpenAI)

Pengaturan konektor ChatGPT (hanya MCP jarak jauh). Tidak ada mcp.json lokal untuk ChatGPT.

  1. ChatGPT (konektor web / desktop) tidak dapat menjalankan proses MCP stdio lokal
  2. Produk ini hanya menyertakan MCP stdio lokal, jadi ChatGPT tidak dapat terhubung langsung
  3. Untuk agen kelas GPT: (1) jalankan MCP yang sama di Cursor / Claude / Gemini CLI, atau (2) panggil REST API halaman ini dengan x-api-key dari Custom Actions / klien API Anda

Anda hanya dapat mendaftarkan konektor ChatGPT jika Anda sendiri meng-host MCP HTTPS jarak jauh (bukan penawaran standar produk).

OpenAI Agents / Responses API juga mengharapkan MCP jarak jauh (HTTP). Server bawaan untuk klien stdio.

Ikhtisar tools (public-api)

Tersedia tools baca dan tulis. Penulisan dapat memulai job berbayar atau mengubah pengaturan organisasi—konfirmasi sebelum memanggil.

Baca

  • list_schedule_results / get_schedule_result (hasil)
  • list_schedule_conditions (kondisi)
  • list_staff / get_staff (staf)
  • get_schedule_defaults (default jadwal)
  • get_emergency_shift_context

Tulis (konfirmasi dulu)

  • submit_schedule (menjalankan job jadwal; dapat dikenai biaya)
  • update_schedule_defaults (default seluruh organisasi)
  • create_staff / update_staff (staf)
  • upsert_weekly_shift_wish (penggantian penuh keinginan mingguan)
  • submit_emergency_shift
  • confirm_schedule_assignments
  • cancel_schedule_condition
  • put_schedule_actual

Beberapa operasi REST (batalkan kondisi, simpan aktual) tidak diekspos via MCP. MCP docs (api-docs) hanya Resources, bukan Tools.

Buat kunci: Manajemen API

Endpoint baca (GET)

URL dasar dan kunci API yang sama dengan POST /v1/schedule. Setiap kartu menampilkan contoh respons JSON minimal sebagai sketsa kontrak.

Daftar menerima query limit (1–100, default 50) dan cursor (token buram dari nextCursor). Jika tidak ada halaman berikutnya, nextCursor dihilangkan.

  • GET{baseUrl}/v1/schedule-results

    Lists schedule-result parent summaries (newest index order).

    Query: limit, cursor.

    Contoh respons

    {
      "items": [
        {
          "conditionId": "cond-11111111-1111-1111-1111-111111111111",
          "status": "completed",
          "candidateCount": 3,
          "createdAt": "2026-04-07T10:00:00.000Z",
          "updatedAt": "2026-04-07T10:05:00.000Z",
          "entityType": "SCHEDULE_RESULT"
        }
      ],
      "nextCursor": "eyJwayI6Ii4uLiJ9"
    }
  • GET{baseUrl}/v1/schedule-results/history

    History search over recent + archive data (same shape as the browser history view).

    Query: from, to (ISO 8601; default service start→now), keyword, eventName (comma-separated INSERT,MODIFY,REMOVE), limit, cursor.

    Contoh respons

    {
      "items": [
        {
          "conditionId": "cond-11111111-1111-1111-1111-111111111111",
          "status": "completed",
          "candidateCount": 2,
          "createdAt": "2026-04-01T09:00:00.000Z",
          "updatedAt": "2026-04-01T09:10:00.000Z",
          "entityType": "SCHEDULE_RESULT"
        }
      ],
      "nextCursor": "eyJwayI6Ii4uLiJ9"
    }
  • GET{baseUrl}/v1/schedule-results/{conditionId}

    One schedule-result parent row (PK/SK stripped).

    Contoh respons

    {
      "scheduleResult": {
        "conditionId": "cond-11111111-1111-1111-1111-111111111111",
        "status": "completed",
        "candidateCount": 3,
        "entityType": "SCHEDULE_RESULT",
        "createdAt": "2026-04-07T10:00:00.000Z",
        "updatedAt": "2026-04-07T10:05:00.000Z"
      }
    }
  • GET{baseUrl}/v1/schedule-results/{conditionId}/resolution

    Resolved optimization output for the condition.

    If status is completed and not yet confirmed, rank-1 may be auto-confirmed on this GET (side effect). Prefer POST …/confirm-assignments for explicit confirmation.

    Contoh respons

    {
      "resolution": {
        "status": "completed",
        "candidates": [
          {
            "rank": 1,
            "assignments": [
              {
                "personId": "550e8400-e29b-41d4-a716-446655440000",
                "personName": "Example Staff",
                "date": "2026-04-07",
                "slotId": "09:00",
                "slotLabel": "09:00"
              }
            ]
          }
        ],
        "confirmedAt": "2026-04-07T10:06:00.000Z",
        "confirmedAssignments": [
          {
            "personId": "550e8400-e29b-41d4-a716-446655440000",
            "personName": "Example Staff",
            "date": "2026-04-07",
            "slotId": "09:00",
            "slotLabel": "09:00"
          }
        ]
      }
    }
  • GET{baseUrl}/v1/schedule-results/{conditionId}/review

    Review payload for manual confirmation UI / clients.

    Contoh respons

    {
      "review": {
        "conditionId": "cond-11111111-1111-1111-1111-111111111111",
        "status": "completed",
        "timeZone": "Asia/Tokyo",
        "calendarDates": ["2026-04-07"],
        "slotIds": ["09:00", "10:00"],
        "slotLabels": ["09:00", "10:00"],
        "requiredByCellKey": {
          "2026-04-07__09:00": 2
        },
        "candidates": [
          {
            "rank": 1,
            "assignments": [
              {
                "personId": "550e8400-e29b-41d4-a716-446655440000",
                "personName": "Example Staff",
                "date": "2026-04-07",
                "slotId": "09:00",
                "slotLabel": "09:00"
              }
            ]
          }
        ],
        "staff": [
          {
            "staffId": "550e8400-e29b-41d4-a716-446655440000",
            "displayName": "Example Staff",
            "allowedCellKeys": ["2026-04-07__09:00", "2026-04-07__10:00"]
          }
        ]
      }
    }
  • GET{baseUrl}/v1/schedule-results/{conditionId}/emergency-shift-context

    Context for building an emergency-shift request. Paid subscription required.

    When the condition is missing, emergencyShiftContext is null.

    Contoh respons

    {
      "emergencyShiftContext": {
        "sourceConditionId": "cond-11111111-1111-1111-1111-111111111111",
        "timeZone": "Asia/Tokyo",
        "calendarDates": ["2026-04-07", "2026-04-08"],
        "staff": [
          {
            "staffId": "550e8400-e29b-41d4-a716-446655440000",
            "displayName": "Example Staff",
            "schedulingRoleIds": [],
            "availabilityByDateYmd": {}
          }
        ],
        "slots": [
          { "slotId": "09:00", "slotLabel": "09:00" }
        ],
        "dayRequirements": [],
        "roleLabelById": {},
        "rosterCandidates": []
      }
    }
  • GET{baseUrl}/v1/schedule-conditions

    Lists schedule-condition index summaries.

    Query: limit, cursor.

    Contoh respons

    {
      "items": [
        {
          "conditionId": "cond-11111111-1111-1111-1111-111111111111",
          "createdAt": "2026-04-07T10:00:00.000Z",
          "scheduleStartDate": "2026-04-07",
          "scheduleEndDate": "2026-04-13"
        }
      ],
      "nextCursor": "eyJwayI6Ii4uLiJ9"
    }
  • GET{baseUrl}/v1/schedule-conditions/{conditionId}

    Condition parent plus reqDays and staffSnapshots (PK/SK stripped).

    Contoh respons

    {
      "condition": {
        "conditionId": "cond-11111111-1111-1111-1111-111111111111",
        "entityType": "SCHEDULE_CONDITION",
        "scheduleStartDate": "2026-04-07",
        "scheduleEndDate": "2026-04-13",
        "timeZone": "Asia/Tokyo"
      },
      "reqDays": [
        {
          "entityType": "SCHEDULE_CONDITION_REQ_DAY",
          "date": "2026-04-07"
        }
      ],
      "staffSnapshots": [
        {
          "entityType": "SCHEDULE_CONDITION_STAFF",
          "staffId": "550e8400-e29b-41d4-a716-446655440000",
          "displayName": "Example Staff"
        }
      ]
    }
  • GET{baseUrl}/v1/schedule-defaults

    Tenant schedule defaults, or null when not saved yet (still HTTP 200).

    Contoh respons

    {
      "scheduleDefaults": {
        "entityType": "SCHEDULE_DEFAULTS",
        "scheduleStartDate": "2026-04-07",
        "scheduleEndDate": "2026-04-13",
        "timeRangeStart": "09:00",
        "timeRangeEnd": "17:00",
        "slotGranularityMinutes": 60,
        "planningHorizon": "week",
        "requirementsByCellKey": {
          "2026-04-07__09:00": 2
        },
        "paidOptimization": {
          "laborLawCompliance": true,
          "balanceStaffLoad": false,
          "honorShiftWishes": true
        }
      }
    }
  • GET{baseUrl}/v1/schedule-actual/{conditionId}

    Saved actual assignments for the condition, or null if none.

    Contoh respons

    {
      "actual": {
        "entityType": "SCHEDULE_ACTUAL",
        "conditionId": "cond-11111111-1111-1111-1111-111111111111",
        "assignments": [
          {
            "personId": "550e8400-e29b-41d4-a716-446655440000",
            "personName": "Example Staff",
            "date": "2026-04-07",
            "slotId": "09:00",
            "slotLabel": "09:00"
          }
        ]
      }
    }
  • GET{baseUrl}/v1/staff/{staffId}/weekly-shift-wish

    Weekly wish row for one staff member, or null if none. Soft-deleted staff → 404.

    Contoh respons

    {
      "weeklyShiftWish": {
        "entityType": "WEEKLY_SHIFT_WISH",
        "staffId": "550e8400-e29b-41d4-a716-446655440000",
        "scheduleStartDate": "2026-04-07",
        "scheduleEndDate": "2026-04-13",
        "timeRangeStart": "09:00",
        "timeRangeEnd": "11:00",
        "wishByCellKey": {
          "2026-04-07__09:00": "HIGH",
          "2026-04-07__10:00": "NONE"
        }
      }
    }
  • GET{baseUrl}/v1/staff

    Active staff members for the tenant (sorted by displayName).

    Contoh respons

    {
      "staff": [
        {
          "staffId": "550e8400-e29b-41d4-a716-446655440000",
          "displayName": "Example Staff",
          "createdAt": "2026-03-01T00:00:00.000Z",
          "updatedAt": "2026-04-01T00:00:00.000Z",
          "laborLawCompliance": true,
          "schedulingRoleIds": [
            "550e8400-e29b-41d4-a716-446655440099"
          ]
        }
      ]
    }
  • GET{baseUrl}/v1/staff/{staffId}

    One staff member including labor / Soft fields when present. Soft-deleted → 404.

    Contoh respons

    {
      "staff": {
        "staffId": "550e8400-e29b-41d4-a716-446655440000",
        "displayName": "Example Staff",
        "createdAt": "2026-03-01T00:00:00.000Z",
        "updatedAt": "2026-04-01T00:00:00.000Z",
        "laborLawCompliance": true,
        "laborFlsaExempt": false,
        "personalMaxWeeklyMinutes": 2400,
        "laborConstraintMask": {
          "schema": "v1"
        },
        "schedulingRoleIds": [
          "550e8400-e29b-41d4-a716-446655440099"
        ],
        "preferredSchedulingRoleIds": [],
        "avoidedSchedulingRoleIds": []
      }
    }

Endpoint tulis (PATCH / POST / PUT / DELETE)

Kunci API dan badan JSON yang sama dengan rute /v1 lain. Setiap kartu menampilkan contoh badan permintaan minimal yang dapat disalin. Pengguna akun, profil perusahaan, dan log audit tetap di aplikasi web — bukan bagian API ini. POST /v1/staff mengembalikan 409 STAFF_LIMIT jika daftar staf melebihi batas penyewa.

Bidang ketenagakerjaan dan Soft prefer/avoid memerlukan langganan berbayar. Ganti UUID, tanggal, dan kunci sel contoh dengan data penyewa Anda.

  • PATCH{baseUrl}/v1/schedule-defaults

    Saves tenant-wide schedule defaults. Paid-tier fields follow your subscription.

    requirementsByCellKey must include every cell in period × slots (missing/extra keys → 400). Cell key = YYYY-MM-DD__HH:mm. planningHorizon: week | two_weeks (month_attendance rejected). Optional: requiredRolesByCellKey, laborLawJurisdiction, usLaborStateCode, linkedMonthPlanStartDate / linkedMonthPlanEndDate, laborModelVersion.

    Contoh badan permintaan

    {
      "scheduleStartDate": "2026-04-07",
      "scheduleEndDate": "2026-04-07",
      "timeRangeStart": "09:00",
      "timeRangeEnd": "11:00",
      "slotGranularityMinutes": 60,
      "planningHorizon": "week",
      "requirementsByCellKey": {
        "2026-04-07__09:00": 2,
        "2026-04-07__10:00": 1
      },
      "requiredRolesByCellKey": {
        "2026-04-07__09:00": {
          "550e8400-e29b-41d4-a716-446655440099": 1
        }
      },
      "paidOptimization": {
        "laborLawCompliance": true,
        "balanceStaffLoad": false,
        "honorShiftWishes": true
      }
    }
  • POST{baseUrl}/v1/staff

    Creates a staff member. Returns 201 with staff JSON.

    Only displayName is accepted.

    Contoh badan permintaan

    {
      "displayName": "Example Staff"
    }
  • POST{baseUrl}/v1/schedule-results/{conditionId}/emergency-shift

    Clones a completed source schedule with absences applied. Returns 201 with new conditionId. Paid subscription required.

    Prefer absentDayPairs. Legacy: absentStaffIds + absentDatesYmd (Cartesian). You may also send absentSlots. Optional substituteDayPairs / substituteSlots open coverage (source must be completed).

    Contoh badan permintaan

    {
      "absentDayPairs": [
        {
          "staffId": "550e8400-e29b-41d4-a716-446655440000",
          "dateYmd": "2026-04-08"
        }
      ],
      "substituteDayPairs": [
        {
          "staffId": "660e8400-e29b-41d4-a716-446655440001",
          "dateYmd": "2026-04-08"
        }
      ]
    }
  • POST{baseUrl}/v1/schedule-results/{conditionId}/confirm-assignments

    Validates and saves manually edited assignments. Returns 200 with { ok: true }.

    assignments is required. relaxAvailability is optional (boolean).

    Contoh badan permintaan

    {
      "assignments": [
        {
          "personId": "550e8400-e29b-41d4-a716-446655440000",
          "personName": "Example Staff",
          "date": "2026-04-07",
          "slotId": "09:00",
          "slotLabel": "09:00"
        }
      ],
      "relaxAvailability": false
    }
  • PATCH{baseUrl}/v1/staff/{staffId}

    Updates one staff member. Send any subset of the fields in the example.

    Personal max minutes: integer or null to clear. laborConstraintMask only when laborLawCompliance is true. schedulingRoleIds / Soft prefer-avoid: UUID arrays; unknown catalog IDs filtered; prefer and avoid must be disjoint. Labor and Soft require paid.

    Contoh badan permintaan

    {
      "displayName": "Example Staff",
      "laborLawCompliance": true,
      "laborFlsaExempt": false,
      "personalMaxWeeklyMinutes": 2400,
      "personalMaxMonthlyMinutes": null,
      "personalMaxThreeMonthMinutes": null,
      "laborConstraintMask": {
        "schema": "v1"
      },
      "schedulingRoleIds": [
        "550e8400-e29b-41d4-a716-446655440099"
      ],
      "preferredSchedulingRoleIds": [
        "550e8400-e29b-41d4-a716-446655440099"
      ],
      "avoidedSchedulingRoleIds": []
    }
  • DELETE{baseUrl}/v1/staff/{staffId}

    Soft-deletes a staff member (sets deletedAt).

    Tanpa badan permintaan.

  • DELETE{baseUrl}/v1/schedule-conditions/{conditionId}

    Marks the condition as cancelled (publicApiCancelledAt); does not delete child rows.

    Tanpa badan permintaan.

  • PUT{baseUrl}/v1/schedule-actual/{conditionId}

    Saves actual shift assignments (validated against the condition grid).

    Same assignment object shape as confirm-assignments.

    Contoh badan permintaan

    {
      "assignments": [
        {
          "personId": "550e8400-e29b-41d4-a716-446655440000",
          "personName": "Example Staff",
          "date": "2026-04-07",
          "slotId": "09:00",
          "slotLabel": "09:00"
        }
      ]
    }
  • PUT{baseUrl}/v1/staff/{staffId}/weekly-shift-wish

    Replaces the weekly wish grid for one staff member (full replace).

    Dates/time range must match the tenant weekly-wish navigation window from schedule defaults. wishByCellKey must cover every cell in that window. Values: NONE | LOW | HIGH.

    Contoh badan permintaan

    {
      "scheduleStartDate": "2026-04-07",
      "scheduleEndDate": "2026-04-13",
      "timeRangeStart": "09:00",
      "timeRangeEnd": "11:00",
      "wishByCellKey": {
        "2026-04-07__09:00": "HIGH",
        "2026-04-07__10:00": "NONE",
        "2026-04-08__09:00": "LOW",
        "2026-04-08__10:00": "NONE"
      }
    }

Webhook penyelesaian

Saat hasil jadwal mencapai status terminal, kami POST notifikasi JSON bertanda tangan ke URL HTTPS Anda. Body tidak menyertakan hasil penuh; ambil detail dengan GET /v1/schedule-results/{conditionId}.

Hasil playground tidak dikirim. Jika webhook dinonaktifkan atau tidak ada URL tersimpan, tidak ada yang dikirim.

Pengaturan

  • Setelah masuk, buka Manajemen API dan simpan URL notifikasi HTTPS.
  • Aktifkan «Aktifkan notifikasi».
  • Salin rahasia tanda tangan yang ditampilkan sekali (tidak dapat ditampilkan lagi; regenerasikan jika hilang).
  • Verifikasi tanda tangan di penerima, lalu GET links.result dengan kunci API bila perlu.

Peristiwa

Jenis peristiwa dan kapan dikirim.

  • schedule.result.terminal

    Status hasil jadwal menjadi completed, no_solution, failed, error, atau canceled

typeKapan
schedule.result.terminalStatus hasil jadwal menjadi completed, no_solution, failed, error, atau canceled

Body permintaan

status hanya terminal. customerId dihilangkan dari body.

{
  "type": "schedule.result.terminal",
  "conditionId": "019ee481-e855-7000-abd8-977cbfd64ffc",
  "status": "completed",
  "occurredAt": "2026-07-16T13:00:54.694Z",
  "links": {
    "result": "{baseUrl}/v1/schedule-results/019ee481-e855-7000-abd8-977cbfd64ffc"
  }
}

Header permintaan

  • Content-Type

    application/json

  • User-Agent

    AutoScheduler-Webhook/1.0

  • X-AutoScheduler-Timestamp

    Detik Unix sebagai string

  • X-AutoScheduler-Signature

    v1=<hex> (lihat verifikasi di bawah)

HeaderDeskripsi
Content-Typeapplication/json
User-AgentAutoScheduler-Webhook/1.0
X-AutoScheduler-TimestampDetik Unix sebagai string
X-AutoScheduler-Signaturev1=<hex> (lihat verifikasi di bawah)

Verifikasi tanda tangan

Hitung digest dari body mentah (sebelum parse JSON) dan Timestamp, lalu bandingkan dengan Signature. Tolak permintaan saat |now − timestamp| melebihi 300 detik (5 menit) kecuali Anda sengaja mengizinkan simpangan jam yang lebih lebar.

HMAC-SHA256(signingSecret, `${timestamp}.${rawBody}`) → hex; nilai header adalah v1=<hex>

Percobaan ulang

Pada 5xx atau timeout kami mencoba ulang otomatis. Kegagalan terus-menerus masuk antrean dead-letter. Notifikasi push browser memakai jalur terpisah.

Daftarkan & aktifkan: Manajemen API

Header

  • x-api-key

    Kunci API terikat ke langganan berbayar Anda (mengidentifikasi penyewa dan batas paket).

  • Content-Type

    application/json

HeaderDeskripsi
x-api-keyKunci API terikat ke langganan berbayar Anda (mengidentifikasi penyewa dan batas paket).
Content-Typeapplication/json

Header respons

Beberapa header respons (seperti ID permintaan) adalah metadata pelacakan, bukan kunci API Anda. Anggap **body** JSON bersifat rahasia bila berisi data perusahaan atau pengguna.

Batas tingkat berbayar (hak)

Batas validasi tipikal untuk kontrak Anda (granularitas 15 menit, rentang jadwal, jumlah staf terdaftar, dan batas terkait).

  • Model penagihan

    Langganan Stripe; biaya produk biasanya mengikuti jumlah kursi staf terdaftar sesuai halaman harga (bukan tagihan per panggilan API).

  • maxScheduleDays

    Hingga 14 hari kalender per pengiriman untuk perencanaan detail dua minggu (batas tetap; kontrak tidak memperpanjang).

  • maxStaffPerSchedule

    Hingga 500 baris staff per POST /v1/schedule (PUBLIC_SCHEDULE_MAX_STAFF; staffId inline di body).

  • maxRosterStaff

    Hingga 30 staf aktif via POST /v1/staff (STAFF_ROSTER_MAX_PAID); 409 STAFF_LIMIT jika terlampaui.

  • allowedGranularities

    [60, 15] — slot 15 menit adalah fitur berbayar; 60 menit juga didukung.

  • maxPayloadBytes

    524288 (512 KiB) UTF-8 kecuali batas lebih tinggi diberikan.

  • strictUnknownRootKeys

    true — kunci tingkat atas atau di staff yang tidak dikenal ditolak

PengaturanAPI berbayar (tipikal)
Model penagihanLangganan Stripe; biaya produk biasanya mengikuti jumlah kursi staf terdaftar sesuai halaman harga (bukan tagihan per panggilan API).
maxScheduleDaysHingga 14 hari kalender per pengiriman untuk perencanaan detail dua minggu (batas tetap; kontrak tidak memperpanjang).
maxStaffPerScheduleHingga 500 baris staff per POST /v1/schedule (PUBLIC_SCHEDULE_MAX_STAFF; staffId inline di body).
maxRosterStaffHingga 30 staf aktif via POST /v1/staff (STAFF_ROSTER_MAX_PAID); 409 STAFF_LIMIT jika terlampaui.
allowedGranularities[60, 15] — slot 15 menit adalah fitur berbayar; 60 menit juga didukung.
maxPayloadBytes524288 (512 KiB) UTF-8 kecuali batas lebih tinggi diberikan.
strictUnknownRootKeystrue — kunci tingkat atas atau di staff yang tidak dikenal ditolak

Kebutuhan kepala per sel tetap bilangan bulat 0 hingga 15. Melebihi batas frekuensi permintaan dapat mengembalikan respons error.

Kunci root yang diizinkan (mode ketat)

Saat mode ketat aktif, hanya kunci tingkat atas berikut yang diterima. Kunci lain mengembalikan UNKNOWN_FIELD.

  • apiVersion
  • timeZone
  • scheduleStartDate
  • scheduleEndDate
  • timeRangeStart
  • timeRangeEnd
  • slotGranularityMinutes
  • requirementsByCell
  • requiredRolesByCell (2026-09-09+)
  • paidOptimization (2026-09-13+)
  • preferredSchedulingRoleIds / avoidedSchedulingRoleIds (2026-09-14 staff)
  • staff

Body permintaan (ringkasan)

Payload mengikuti model permintaan jadwal publik berbayar: tanggal kalender, zona waktu, grid slot (60 atau 15 menit di API berbayar), kebutuhan per sel, dan ketersediaan staf. Yurisdiksi hukum kerja tidak ada di JSON. paidOptimization opsional untuk apiVersion 2026-09-13+ (jika tidak, default tenant). Field Soft prefer/avoid staf memerlukan 2026-09-14. Lihat «Hukum kerja & flag berbayar». Jangan sertakan kunci DynamoDB atau tipe entitas internal di body.

  • apiVersion — Opsional. Abaikan atau "2026-04-01" = legacy. "2026-09-09" = peran; "2026-09-13" = peran + paidOptimization; "2026-09-14" = Soft prefer/avoid. Versi terbaru: 2026-09-14.
  • Format cellKey — Kunci di requirementsByCell dan availableCells harus cocok dengan `${date}__${slotId}` dengan date YYYY-MM-DD dalam rentang dan slotId dari slot yang dihitung untuk rentang waktu dan granularitas Anda (sama seperti `cellKey` di helper playground).

Tabel referensi cepat

  • timeZone

    Tipe
    string
    Wajib
    Ya

    Zona waktu IANA untuk menafsirkan tanggal dan slot.

  • scheduleStartDate / scheduleEndDate

    Tipe
    string (YYYY-MM-DD)
    Wajib
    Ya

    Rentang kalender inklusif; mulai ≤ akhir.

  • timeRangeStart / timeRangeEnd

    Tipe
    string (HH:mm)
    Wajib
    Ya

    Rentang jam dinding yang mendefinisikan kolom slot; harus menghasilkan setidaknya satu slot.

  • slotGranularityMinutes

    Tipe
    60 | 15
    Wajib
    Ya

    API berbayar: 60 (per jam) atau 15 (15 menit). Harus ada di allowedGranularities.

  • requirementsByCell

    Tipe
    object
    Wajib
    Ya

    Kunci = cellKey di grid yang dihitung; nilai = bilangan bulat 0–15.

  • requiredRolesByCell

    Tipe
    object
    Wajib
    Tidak — hanya 2026-09-09

    cellKey → roleId→need. Jumlah need per sel ≤ requirementsByCell. Versi lama → UNKNOWN_FIELD.

  • staff

    Tipe
    array
    Wajib
    Ya

    Tidak kosong; ukuran maks. sesuai batas; setiap item: staffId, displayName, availableCells / laborConstraintMask / schedulingRoleIds (2026-09-09+) / Soft prefer-avoid (2026-09-14) opsional.

BidangTipeWajibCatatan
timeZonestringYaZona waktu IANA untuk menafsirkan tanggal dan slot.
scheduleStartDate / scheduleEndDatestring (YYYY-MM-DD)YaRentang kalender inklusif; mulai ≤ akhir.
timeRangeStart / timeRangeEndstring (HH:mm)YaRentang jam dinding yang mendefinisikan kolom slot; harus menghasilkan setidaknya satu slot.
slotGranularityMinutes60 | 15YaAPI berbayar: 60 (per jam) atau 15 (15 menit). Harus ada di allowedGranularities.
requirementsByCellobjectYaKunci = cellKey di grid yang dihitung; nilai = bilangan bulat 0–15.
requiredRolesByCellobjectTidak — hanya 2026-09-09cellKey → roleId→need. Jumlah need per sel ≤ requirementsByCell. Versi lama → UNKNOWN_FIELD.
staffarrayYaTidak kosong; ukuran maks. sesuai batas; setiap item: staffId, displayName, availableCells / laborConstraintMask / schedulingRoleIds (2026-09-09+) / Soft prefer-avoid (2026-09-14) opsional.

Referensi field (nilai yang diizinkan)

Aturan field berikut cocok dengan validator API publik. Kirim angka JSON sebagai angka sebenarnya (bukan string). Setelah validasi, server dapat menyimpan default baris induk (optimasi berbayar, yurisdiksi hukum kerja, versi model) yang bukan kunci permintaan — lihat «Hukum kerja & flag berbayar».

apiVersion

string | dihilangkan · Wajib: Tidak — opsional

Nilai yang diizinkan

  • Dihilangkan: diterima (perilaku terbaru).
  • Jika ada, harus "2026-04-01", "2026-09-09", "2026-09-13", atau "2026-09-14". Versi terbaru yang dipublikasikan: 2026-09-14.
  • String lain ditolak (TYPE_ERROR).

Perilaku

  • Dibandingkan setelah penanganan setara trim di sanitizeApiVersion.
  • Versi memilih kumpulan kunci tingkat atas dan objek staff yang diizinkan (peran pada 2026-09-09+; paidOptimization pada 2026-09-13+; Soft prefer/avoid pada 2026-09-14).

Error umum

  • TYPE_ERRORNilai apiVersion tidak didukung.

timeZone

string · Wajib: Ya

Nilai yang diizinkan

  • Format satu string. API TIDAK menerbitkan enum tertutup semua zona: server memvalidasi secara dinamis.
  • Validasi cocok dengan `isValidIanaTimeZone`: Luxon `DateTime.now().setZone(zone).isValid` harus true.
  • Gunakan pengidentifikasi IANA kanonik, mis. `Asia/Tokyo`, `America/New_York`, `Europe/Berlin`, `UTC`.
  • Jangan mengandalkan hanya singkatan (`EST`, `JST`, `GMT`) — bukan ID zona IANA yang stabil dan mungkin ditolak.
  • Daftar referensi: distribusi IANA (https://www.iana.org/time-zones) atau API zona waktu platform Anda.

Perilaku

  • Digunakan dengan tanggal dan waktu slot dalam normalisasi hilir.
  • Jika perlu daftar tetap di klien, turunkan dari aturan yang sama (ID IANA), jangan mengharapkan enum server di skema JSON.

Error umum

  • INVALID_TIME_ZONEHilang, kosong, atau zona IANA tidak valid.

scheduleStartDate, scheduleEndDate

string, string · Wajib: Ya — keduanya

Nilai yang diizinkan

  • Harus cocok /^\d{4}-\d{2}-\d{2}$/ (setelah trim).
  • Tanggal kalender nyata; rentang inklusif harus menghasilkan setidaknya satu hari melalui enumerateDates.
  • Jumlah hari dalam rentang tidak boleh melebihi maxScheduleDays (API berbayar: batas tetap 14 hari untuk perencanaan dua minggu).

Perilaku

  • scheduleStartDate harus pada atau sebelum scheduleEndDate.

Error umum

  • INVALID_DATE_RANGEFormat buruk, tanggal tidak valid, atau rentang kosong.
  • SCHEDULE_SPAN_TOO_LONGLebih dari maxScheduleDays hari.

timeRangeStart, timeRangeEnd

string, string · Wajib: Ya — keduanya

Nilai yang diizinkan

  • String tidak kosong (trim) diinterpretasikan dengan enumerasi slot yang sama seperti UI (`enumerateSlotsByGranularity`).
  • Pasangan harus menghasilkan setidaknya satu slot; jika tidak, validasi gagal.

Perilaku

  • Bersama slotGranularityMinutes, mendefinisikan nilai slotId untuk cellKey.

Error umum

  • INVALID_TIME_RANGENilai hilang atau nol slot untuk rentang.

slotGranularityMinutes

number (angka JSON) · Wajib: Ya

Nilai yang diizinkan

  • Harus tepat 60 atau 15 (bukan string).
  • Juga harus muncul di allowedGranularities. Di API berbayar keduanya biasanya diaktifkan; jika 15 dinonaktifkan untuk penyewa Anda, INVALID_GRANULARITY.

Perilaku

  • Mendefinisikan jumlah slot bersama rentang waktu.

Error umum

  • INVALID_GRANULARITYBukan 60/15, atau tidak diizinkan untuk paket.

requirementsByCell

Record<string, number> · Wajib: Ya

Nilai yang diizinkan

  • Harus objek JSON biasa (bukan array).
  • Setiap kunci harus cellKey di grid yang diharapkan (tanggal × slotIds). Kunci tidak dikenal → UNKNOWN_CELL_KEY.
  • Setiap nilai harus angka JSON, bilangan bulat, antara 0 dan 15 inklusif.
  • Sel yang dihilangkan diperlakukan sebagai kebutuhan 0 (hanya sel dengan kebutuhan ≥ 1 ikut SHORTFALL).

Perilaku

  • Kunci dibandingkan setelah trim melalui sanitizeCellKey.

Error umum

  • INVALID_REQUIREMENTSBukan objek atau nilai numerik tidak valid untuk kunci.
  • UNKNOWN_CELL_KEYKunci tidak dalam grid tanggal × slot yang dihitung.

requiredRolesByCell

object | omitted · Wajib: Tidak — opsional; hanya apiVersion 2026-09-09

Nilai yang diizinkan

  • Hanya diterima saat apiVersion adalah "2026-09-09". Diabaikan / 2026-04-01 → UNKNOWN_FIELD.
  • Harus objek JSON biasa. Setiap kunci adalah cellKey di grid requirements.
  • Setiap nilai adalah objek yang memetakan roleId (UUID) → need bilangan bulat ≥ 1.
  • Untuk setiap sel, sum(need) harus ≤ requirementsByCell[cell] (atau 0 jika diabaikan).
  • Jalur submit hanya memvalidasi bentuk UUID dan jumlah (tanpa lookup katalog).

Perilaku

  • Nilai dinormalisasi dan divalidasi (ID peran UUID; jumlah need ≤ headcount).
  • Disimpan sebagai requiredRolesBySlot pada baris kebutuhan harian.

Kesalahan umum

  • UNKNOWN_FIELDDikirim pada apiVersion lama.
  • INVALID_REQUIREMENTSBentuk salah, roleId bukan UUID, atau jumlah melebihi headcount.
  • UNKNOWN_CELL_KEYcellKey tidak ada di grid yang dihitung.

staff

array · Wajib: Ya — array tidak kosong

Nilai yang diizinkan

  • Panjang antara 1 dan maxStaffPerSchedule (default 500 untuk POST /v1/schedule; terpisah dari batas roster POST /v1/staff).
  • Setiap elemen harus objek biasa dengan kunci yang diizinkan untuk apiVersion: staffId, displayName, availableCells, laborConstraintMask; plus schedulingRoleIds pada 2026-09-09+; plus preferredSchedulingRoleIds / avoidedSchedulingRoleIds pada 2026-09-14 (mode ketat).
  • staffId dan displayName harus lulus sanitasi (lihat bagian Sanitasi).
  • staffId harus unik di array (DUPLICATE_STAFF_ID).

Perilaku

  • Urutan dipertahankan untuk penghitungan ketersediaan.

Error umum

  • INVALID_STAFFArray kosong, terlalu banyak baris, objek buruk, atau sanitasi gagal.
  • UNKNOWN_FIELDKunci ekstra pada objek staff dalam mode ketat.
  • DUPLICATE_STAFF_IDstaffId yang sama dua kali.

staff[].availableCells

string[] | dihilangkan · Wajib: Tidak — opsional

Nilai yang diizinkan

  • Jika dihilangkan: staf dianggap tersedia di semua sel grid (implementasi memakai null «semua sel»).
  • Jika ada: harus array JSON string; setiap string tidak kosong harus cellKey di grid yang diharapkan.
  • String kosong dalam array tidak valid (INVALID_AVAILABLE_CELL).

Pemeriksaan SHORTFALL

  • Untuk setiap sel dengan kebutuhan ≥ 1, jumlah staf yang dihitung tersedia harus ≥ kebutuhan, jika tidak SHORTFALL_CELLS.

Error umum

  • INVALID_AVAILABLE_CELLKunci sel tidak dikenal atau entri kosong.
  • SHORTFALL_CELLSStaf tidak cukup untuk kebutuhan sel.

staff[].schedulingRoleIds / Soft prefer-avoid

string[] | omitted · Wajib: Tidak — opsional; peran pada 2026-09-09+; Soft pada 2026-09-14

Nilai yang diizinkan

  • schedulingRoleIds: diterima pada apiVersion 2026-09-09+. Soft preferredSchedulingRoleIds / avoidedSchedulingRoleIds: hanya 2026-09-14. Versi lebih lama → UNKNOWN_FIELD.
  • Array JSON string UUID. Duplikat dihapus. Soft prefer ∩ avoid harus kosong.
  • Array kosong / diabaikan = tidak ada kerangka peran Hard / preferensi Soft pada snapshot kondisi.
  • Jalur submit tidak memfilter terhadap katalog tenant; PATCH /v1/staff/{staffId} memfilter (PATCH Soft berbayar).

Perilaku

  • Nilai dinormalisasi (string UUID; duplikat dihapus). Tumpang tindih Soft → INVALID_STAFF.
  • Disalin ke baris snapshot kondisi staf saat tidak kosong.

Kesalahan umum

  • UNKNOWN_FIELDDikirim pada apiVersion yang tidak mengizinkan kunci.
  • INVALID_STAFFBukan array, elemen bukan UUID, atau tumpang tindih Soft prefer/avoid.

Hukum kerja & optimasi berbayar (tidak di body JSON)

t/a — disimpan di server · Dalam permintaan: Tidak — jangan kirim kunci ini

Yang disimpan API pada baris induk

  • API publik hanya menerima kunci tingkat atas dan objek staf yang diizinkan untuk apiVersion Anda. Jangan kirim laborLawJurisdiction, usLaborStateCode, atau laborModelVersion. paidOptimization opsional untuk apiVersion 2026-09-13+. Field Soft prefer/avoid staf memerlukan 2026-09-14.
  • Saat mengirim, server mengatur SCHEDULE_CONDITION induk dari default bersama: paidOptimization dari body (apiVersion 2026-09-13+) atau SCHEDULE_DEFAULTS tenant jika diabaikan; jika tidak, DEFAULT_PAID_OPTIMIZATION (laborLawCompliance induk dipaksa true). laborLawJurisdiction / usLaborStateCode / laborModelVersion diwarisi dari SCHEDULE_DEFAULTS tenant (cadangan JP / GENERIC / model sesuai yurisdiksi).
  • Kendala hukum kerja bergaya undang-undang di optimizer memerlukan flag kepatuhan induk dan per staf aktif. Flag per staf tidak ada di JSON: server mewarisi dari daftar staf tenant (staffId yang tidak terdaftar default aktif). POST /v1/staff juga default aktif; matikan per orang dengan PATCH berbayar /v1/staff/{staffId}.
  • Model hukum kerja adalah perkiraan untuk penjadwalan, bukan nasihat hukum. Katalog: .

Dokumentasi

  • Detail lengkap: this page dan §3.1.

Jika mengirim kunci yang dilarang

  • UNKNOWN_FIELDMode ketat menolak properti root atau staff yang tidak dikenal.

Aturan sanitasi

Diterapkan sebelum atau selama validasi. Aturan ini menjelaskan mengapa nilai dapat ditolak sebagai INVALID_STAFF.

staffId

  • Trim; panjang 1–128.
  • Karakter harus cocok /^[a-zA-Z0-9._-]+$/ (tanpa garis miring atau backslash).

displayName

  • Hapus karakter kontrol dan zero-width; rapatkan spasi; trim.
  • Kurung sudut < dan > tidak diizinkan.
  • Maks. 128 karakter setelah sanitasi; tidak boleh kosong.

Kunci sel (requirements / availableCells)

  • Kunci di-trim; harus cocok persis dengan string cellKey di grid yang dihitung.

Respons sukses

202 Accepted

Body lolos validasi dan kondisi ditulis; optimasi dapat berlanjut secara asinkron. Handler dapat mengembalikan JSON dengan conditionId dan field terkait.

Daftar kode error (lengkap)

Error validasi mengembalikan informasi terstruktur dengan `code` yang stabil. Parsing sebelum validasi (INVALID_JSON, PAYLOAD_TOO_LARGE). Kegagalan persistensi dapat muncul sebagai DYNAMODB_ERROR. PATCH /v1/schedule-defaults dapat mengembalikan SCHEDULE_DEFAULTS_SAVE_FAILED (HTTP 400) dengan detail.

  • INVALID_JSON

    Body bukan JSON yang valid.

  • PAYLOAD_TOO_LARGE

    Panjang byte UTF-8 melebihi maxPayloadBytes (default 512 KiB).

  • TYPE_ERROR

    Tipe JSON salah atau string apiVersion tidak didukung.

  • UNKNOWN_FIELD

    Mode ketat: properti tidak diizinkan pada root atau objek staff.

  • INVALID_TIME_ZONE

    timeZone hilang atau bukan nama IANA yang valid.

  • INVALID_DATE_RANGE

    Tanggal bukan YYYY-MM-DD, rentang tidak valid, atau enumerasi kosong.

  • SCHEDULE_SPAN_TOO_LONG

    Terlalu banyak hari antara mulai dan akhir (lihat maxScheduleDays).

  • INVALID_TIME_RANGE

    Rentang waktu hilang atau menghasilkan nol slot.

  • INVALID_GRANULARITY

    slotGranularityMinutes bukan 60/15 atau tidak diizinkan paket.

  • INVALID_REQUIREMENTS

    requirementsByCell bukan objek atau hitungan bukan bilangan bulat 0–15.

  • UNKNOWN_CELL_KEY

    Kunci tidak dalam grid jadwal yang dihitung.

  • INVALID_STAFF

    staff kosong, terlalu besar, baris buruk, atau sanitasi gagal.

  • DUPLICATE_STAFF_ID

    Nilai staffId duplikat.

  • INVALID_AVAILABLE_CELL

    Entri kosong atau tidak dikenal di availableCells.

  • SHORTFALL_CELLS

    Ketersediaan staf tidak cukup vs kebutuhan.

  • DYNAMODB_ERROR

    Error sementara atau persistensi setelah validasi (tergantung handler).

  • SCHEDULE_DEFAULTS_SAVE_FAILED

    PATCH /v1/schedule-defaults: validasi atau aturan bisnis gagal (lihat error.details).

  • LABOR_COMPLIANCE_REQUIRED

    PATCH /v1/staff/{staffId}: laborConstraintMask dikirim saat laborLawCompliance false.

KodeArti
INVALID_JSONBody bukan JSON yang valid.
PAYLOAD_TOO_LARGEPanjang byte UTF-8 melebihi maxPayloadBytes (default 512 KiB).
TYPE_ERRORTipe JSON salah atau string apiVersion tidak didukung.
UNKNOWN_FIELDMode ketat: properti tidak diizinkan pada root atau objek staff.
INVALID_TIME_ZONEtimeZone hilang atau bukan nama IANA yang valid.
INVALID_DATE_RANGETanggal bukan YYYY-MM-DD, rentang tidak valid, atau enumerasi kosong.
SCHEDULE_SPAN_TOO_LONGTerlalu banyak hari antara mulai dan akhir (lihat maxScheduleDays).
INVALID_TIME_RANGERentang waktu hilang atau menghasilkan nol slot.
INVALID_GRANULARITYslotGranularityMinutes bukan 60/15 atau tidak diizinkan paket.
INVALID_REQUIREMENTSrequirementsByCell bukan objek atau hitungan bukan bilangan bulat 0–15.
UNKNOWN_CELL_KEYKunci tidak dalam grid jadwal yang dihitung.
INVALID_STAFFstaff kosong, terlalu besar, baris buruk, atau sanitasi gagal.
DUPLICATE_STAFF_IDNilai staffId duplikat.
INVALID_AVAILABLE_CELLEntri kosong atau tidak dikenal di availableCells.
SHORTFALL_CELLSKetersediaan staf tidak cukup vs kebutuhan.
DYNAMODB_ERRORError sementara atau persistensi setelah validasi (tergantung handler).
SCHEDULE_DEFAULTS_SAVE_FAILEDPATCH /v1/schedule-defaults: validasi atau aturan bisnis gagal (lihat error.details).
LABOR_COMPLIANCE_REQUIREDPATCH /v1/staff/{staffId}: laborConstraintMask dikirim saat laborLawCompliance false.

Contoh JSON minimal

{
  "apiVersion": "2026-04-01",
  "timeZone": "Asia/Tokyo",
  "scheduleStartDate": "2026-04-07",
  "scheduleEndDate": "2026-04-13",
  "timeRangeStart": "08:00",
  "timeRangeEnd": "20:00",
  "slotGranularityMinutes": 60,
  "requirementsByCell": {
    "2026-04-07__slot-0": 2
  },
  "staff": [
    {
      "staffId": "550e8400-e29b-41d4-a716-446655440000",
      "displayName": "Example",
      "availableCells": ["2026-04-07__slot-0"]
    }
  ]
}

Di halaman ini. POST /v1/schedule: referensi field dan tabel singkat. Default penyewa: endpoint tulis → PATCH /v1/schedule-defaults. Labor / Soft: PATCH /v1/staff/{staffId}. Paket: halaman harga.