Route incoming IllyVoIP API calls around holidays and opening hours

Apply your application’s timezone, weekly hours and holiday exceptions before transferring an incoming IllyVoIP Voice API call.

For an API-controlled incoming number, your application can choose an open-hours or closed-hours path before transferring the caller. Keep that calendar in your application and use IllyVoIP call control for the resulting action. This guide does not describe a new Portal holiday-calendar switch.

Run Voice API requests on your backend with X-Api-Key authentication and JSON bodies. Use the API base https://api.illyvoip.com. Persist a separate Idempotency-Key for each paid call or prompt action and reuse that action’s key while its outcome is pending. Calling and speech can incur charges. Examples use placeholders and describe application logic; they are not records of completed calls.

1. Define one authoritative schedule

  1. Choose the business timezone using an IANA timezone name, such as Europe/Berlin.
  2. Define weekly opening intervals and decide whether closing time is exclusive.
  3. Add dated exceptions for holidays, special opening hours and closures.
  4. Assign responsibility for reviewing the calendar before each holiday period.

Evaluate the call’s decision time in the business timezone, not the server’s local timezone. A date that is already tomorrow on the server may still be today for the business. Treat an explicit holiday closure as an override of the weekly schedule, not as an empty value that falls back to ordinary hours.

2. Test the schedule as a pure function

The following Python helper demonstrates same-day intervals. Weekdays use Monday = 0. An empty exception list means closed for that local date. Split overnight opening into intervals on the relevant dates; this helper intentionally rejects a reversed interval.

from datetime import datetime
from zoneinfo import ZoneInfo

def is_open(at, timezone, weekly, exceptions):
    if at.tzinfo is None or at.utcoffset() is None:
        raise ValueError("Use an aware decision time")
    local = at.astimezone(ZoneInfo(timezone))
    day = local.date().isoformat()
    periods = exceptions.get(day, weekly.get(local.weekday(), []))
    minute = local.hour * 60 + local.minute
    for start, end in periods:
        if not (0 <= start < end <= 1440):
            raise ValueError("Use same-day minute intervals")
    return any(start <= minute < end for start, end in periods)

weekly = {d: [(9 * 60, 17 * 60)] for d in range(5)}
exceptions = {"2026-12-25": []}
# Pass an aware timestamp for the actual routing decision.

The helper defines a policy, not a full calendar service. Store and validate configuration before using it for real calls. Decide how your business treats repeated or skipped local times around daylight-saving changes and include those cases in tests. A timezone conversion does not make an ambiguous business policy disappear.

3. Acquire the eligible incoming call once

Follow the incoming Voice API guide to identify a call your integration is allowed to answer. Check its API-answer eligibility and call state. Use the documented answer action with its public call reference and retain the returned call-control reference. Serialize your controller so two workers do not both answer or route the same call.

Evaluate the schedule once for that routing decision and save the selected policy version and outcome. Recomputing halfway through a transfer can produce contradictory actions when the clock crosses closing time. Do not interpret a calendar-service failure as permission to send the caller to an arbitrary destination.

4. Execute the chosen path

  1. For an open result, post to /api/v1/voice/call-control/transfer with call_control_id and target containing the configured type (for example sip_user) and its permitted value.
  2. Persist transfer_id and follow /api/v1/voice/call-control/transfer-status; inspect terminal and resume_original before choosing a fallback.
  3. For a closed result, speak the approved closure message and follow playback completion before hanging up, or use another explicitly configured closed-hours destination.
  4. If transfer fails or returns control to the original call, follow one bounded fallback instead of starting an uncontrolled transfer loop.

The destination must be valid for your account and the intended workflow. A schedule result does not prove that the receiving team is available. Keep the closed message accurate and avoid promising a reopening time unless the same calendar supports that statement.

5. Test boundaries and failures

Check one minute before opening, exact opening, exact closing, weekends, a holiday override, special hours and daylight-saving dates. Then test a stale call, duplicate worker, unavailable calendar, failed transfer and interrupted response. Use local fixtures before an authorized paid call test. Retain the call reference, policy version and selected outcome without logging credentials or unnecessary caller data.

Related guides

Reference

Current instructions and technical reference: IllyVoIP API documentation, Python: IANA timezone support.

Reviewed 12 October 2026 against the current IllyVoIP controls, implementation and applicable references. Available options depend on account permissions and service state.