> ## Documentation Index
> Fetch the complete documentation index at: https://platform-docs.sarj.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a Sarj.ai schedule config (retry policy) for outbound calls

> Create a reusable retry policy: how many times to retry a call the customer did not answer, how long to wait between attempts, and in which daily window. Reference the returned id as schedule_config_id when creating calls. This endpoint is create-only today — there is no way to fetch, list, update, or disable a config after creation; that ships in a follow-up.



## OpenAPI

````yaml /api-reference/openapi.json post /schedule-configs
openapi: 3.1.0
info:
  title: Sarj.ai Developer API
  description: >
    Public API for programmatic access to the **Sarj.ai voice platform**.


    > [!TIP]

    > **New here?** Start with the [Getting Started
    guide](https://platform-docs.sarj.ai/getting-started)

    > to go from API key to first call in under 5 minutes.

    >

    > **Building with AI agents?** See the [MCP Server
    guide](https://platform-docs.sarj.ai/mcp-server)

    > to connect Claude Code, Cursor, or any MCP-compatible agent.


    ---


    ## Authentication


    All authenticated endpoints require a **Bearer token** in the
    `Authorization`

    header:


    ```

    Authorization: Bearer <your-api-key>

    ```


    Generate an API key from
    [platform.sarj.ai/api-keys](https://platform.sarj.ai/api-keys).


    > [!WARNING]

    > If you receive a `401 Unauthorized` response, your key may be invalid,

    > expired, or missing. Check the `error.type` field in the response body.


    ---


    ## Response Format


    **Success**


    ```json

    {
      "data": { ... },
      "meta": { "request_id": "550e8400-e29b-41d4-a716-446655440000" }
    }

    ```


    **Error**


    ```json

    {
      "error": {
        "type": "unauthorized",
        "message": "Authentication required."
      },
      "meta": { "request_id": "550e8400-e29b-41d4-a716-446655440000" }
    }

    ```


    Always branch on `error.type` — the `message` field is for humans only.


    ---


    ## Support


    Include `meta.request_id` in all support tickets for faster resolution.
  license:
    name: Apache 2.0
    identifier: Apache-2.0
  version: 1.0.0
servers:
  - url: https://platform-api.sarj.ai/api/v1
    description: Production
security:
  - ApiKeyAuth: []
tags:
  - name: System
    description: Service health and status.
  - name: Calls
    description: Create outbound voice calls and retrieve call details and transcripts.
  - name: Schedule Configs
    description: Create and manage retry policies for scheduled outbound calls.
externalDocs:
  description: Sarj.ai Documentation
  url: https://platform-docs.sarj.ai
paths:
  /schedule-configs:
    post:
      tags:
        - Schedule Configs
      summary: Create a Sarj.ai schedule config (retry policy) for outbound calls
      description: >-
        Create a reusable retry policy: how many times to retry a call the
        customer did not answer, how long to wait between attempts, and in which
        daily window. Reference the returned id as schedule_config_id when
        creating calls. This endpoint is create-only today — there is no way to
        fetch, list, update, or disable a config after creation; that ships in a
        follow-up.
      operationId: createScheduleConfig
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateScheduleConfigRequest'
        required: true
      responses:
        '201':
          description: The schedule config was created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse_PublicScheduleConfig_'
        '400':
          description: Malformed request body.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Missing or invalid API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Scheduling disabled, or no organization.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: Validation error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  schemas:
    CreateScheduleConfigRequest:
      properties:
        enabled:
          type: boolean
          title: Enabled
          description: >-
            Whether calls referencing this config retry. Disabling cancels
            pending retries at release time.
          default: true
        max_retries:
          type: integer
          maximum: 10
          minimum: 1
          title: Max Retries
          description: >-
            Maximum retry attempts after the first call reaches the customer
            (1-10).
          examples:
            - 2
        wait_between:
          type: string
          format: duration
          title: Wait Between
          description: >-
            Wait between attempts, measured from the end of the previous call.
            Accepts seconds (7200) or an ISO 8601 duration ('PT2H'). 60 seconds
            to 30 days.
          examples:
            - PT2H
        retry_window:
          anyOf:
            - $ref: '#/components/schemas/TimeWindow'
            - type: 'null'
          description: >-
            Daily window retries may dial in, as start/end wall-clock edges in
            the config timezone. Omitted, retries dial at any hour.
        timezone:
          anyOf:
            - type: string
            - type: 'null'
          title: Timezone
          description: >-
            IANA timezone the retry_window is evaluated in. Omitted, the
            scenario's timezone applies.
          examples:
            - Asia/Riyadh
        expire_after:
          anyOf:
            - type: string
              format: duration
            - type: 'null'
          title: Expire After
          description: >-
            Stop retrying this long after the first call ended, whichever of
            attempts/expiry hits first. 1 hour to 7 days (the platform ceiling);
            omitted, only max_retries and the ceiling bound the group.
          examples:
            - P3D
      additionalProperties: false
      type: object
      required:
        - max_retries
        - wait_between
      title: CreateScheduleConfigRequest
    ApiResponse_PublicScheduleConfig_:
      properties:
        data:
          $ref: '#/components/schemas/PublicScheduleConfig'
        meta:
          $ref: '#/components/schemas/ResponseMeta'
      additionalProperties: false
      type: object
      required:
        - data
      title: ApiResponse[PublicScheduleConfig]
    ErrorResponse:
      properties:
        error:
          oneOf:
            - $ref: '#/components/schemas/ValidationErrorPayload'
            - $ref: '#/components/schemas/UnauthorizedPayload'
            - $ref: '#/components/schemas/NotFoundPayload'
            - $ref: '#/components/schemas/InternalErrorPayload'
            - $ref: '#/components/schemas/PhoneNumberBlockedPayload'
            - $ref: '#/components/schemas/CallLimitExceededPayload'
            - $ref: '#/components/schemas/OutboundCallFailedPayload'
            - $ref: '#/components/schemas/ScenarioNotFoundPayload'
            - $ref: '#/components/schemas/ScenarioForbiddenPayload'
            - $ref: '#/components/schemas/ScenarioInvalidConfigPayload'
            - $ref: '#/components/schemas/NoOrganizationPayload'
            - $ref: '#/components/schemas/CallNotFoundPayload'
            - $ref: '#/components/schemas/OauthInvalidRedirectUriPayload'
            - $ref: '#/components/schemas/SchedulingDisabledPayload'
            - $ref: '#/components/schemas/InvalidScheduleTimePayload'
            - $ref: '#/components/schemas/ScheduleConfigNotFoundPayload'
            - $ref: '#/components/schemas/CallNotPendingPayload'
          title: Error
          discriminator:
            propertyName: type
            mapping:
              call_limit_exceeded:
                $ref: '#/components/schemas/CallLimitExceededPayload'
              call_not_found:
                $ref: '#/components/schemas/CallNotFoundPayload'
              call_not_pending:
                $ref: '#/components/schemas/CallNotPendingPayload'
              internal_error:
                $ref: '#/components/schemas/InternalErrorPayload'
              invalid_schedule_time:
                $ref: '#/components/schemas/InvalidScheduleTimePayload'
              no_organization:
                $ref: '#/components/schemas/NoOrganizationPayload'
              not_found:
                $ref: '#/components/schemas/NotFoundPayload'
              oauth_invalid_redirect_uri:
                $ref: '#/components/schemas/OauthInvalidRedirectUriPayload'
              outbound_call_failed:
                $ref: '#/components/schemas/OutboundCallFailedPayload'
              phone_number_blocked:
                $ref: '#/components/schemas/PhoneNumberBlockedPayload'
              scenario_forbidden:
                $ref: '#/components/schemas/ScenarioForbiddenPayload'
              scenario_invalid_config:
                $ref: '#/components/schemas/ScenarioInvalidConfigPayload'
              scenario_not_found:
                $ref: '#/components/schemas/ScenarioNotFoundPayload'
              schedule_config_not_found:
                $ref: '#/components/schemas/ScheduleConfigNotFoundPayload'
              scheduling_disabled:
                $ref: '#/components/schemas/SchedulingDisabledPayload'
              unauthorized:
                $ref: '#/components/schemas/UnauthorizedPayload'
              validation_error:
                $ref: '#/components/schemas/ValidationErrorPayload'
        meta:
          $ref: '#/components/schemas/ResponseMeta'
      additionalProperties: false
      type: object
      required:
        - error
      title: ErrorResponse
      description: |-
        Standard envelope for all public API error responses.

        `error` is a discriminated union — branch on `error.type` to access
        variant-specific fields. Clients MUST treat unknown `type` values as
        retryable internal errors to preserve forward compatibility.
    TimeWindow:
      properties:
        start_edge:
          $ref: '#/components/schemas/TimeEdge'
        end_edge:
          $ref: '#/components/schemas/TimeEdge'
      additionalProperties: false
      type: object
      required:
        - start_edge
        - end_edge
      title: TimeWindow
    PublicScheduleConfig:
      properties:
        id:
          type: string
          title: Id
          description: >-
            Unique schedule config identifier. Pass it as schedule_config_id
            when creating calls.
          examples:
            - 01890000-0000-7000-8000-000000000000
        created_at:
          type: string
          format: date-time
          title: Created At
          description: Timestamp when the config was created.
        enabled:
          type: boolean
          title: Enabled
          description: Whether calls referencing this config retry.
        max_retries:
          type: integer
          title: Max Retries
          description: Maximum retry attempts after the first call reaches the customer.
        wait_between:
          type: string
          format: duration
          title: Wait Between
          description: Wait between attempts (ISO 8601 duration).
        retry_window:
          anyOf:
            - $ref: '#/components/schemas/TimeWindow'
            - type: 'null'
          description: Daily window retries may dial in.
        timezone:
          anyOf:
            - type: string
            - type: 'null'
          title: Timezone
          description: IANA timezone the retry_window is evaluated in.
        expire_after:
          anyOf:
            - type: string
              format: duration
            - type: 'null'
          title: Expire After
          description: How long after the first call's end the group stops retrying.
      additionalProperties: false
      type: object
      required:
        - id
        - created_at
        - enabled
        - max_retries
        - wait_between
      title: PublicScheduleConfig
    ResponseMeta:
      properties:
        request_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Request Id
          description: >-
            Unique identifier for this request, mirrored in the `X-Request-ID`
            response header. Supply your own via the `X-Request-ID` request
            header (max 128 chars, ASCII printable); otherwise the server
            generates a UUID v4. Include in support tickets.
          examples:
            - 550e8400-e29b-41d4-a716-446655440000
      additionalProperties: false
      type: object
      title: ResponseMeta
      description: Contains request-level metadata included with every public API response.
    ValidationErrorPayload:
      properties:
        message:
          type: string
          title: Message
          description: >-
            Human-readable summary. Do not parse programmatically — branch on
            `type`.
        type:
          type: string
          const: validation_error
          title: Type
          default: validation_error
        field_violations:
          items:
            $ref: '#/components/schemas/FieldViolation'
          type: array
          title: Field Violations
          description: Per-field validation details.
      additionalProperties: false
      type: object
      required:
        - message
        - field_violations
      title: ValidationErrorPayload
    UnauthorizedPayload:
      properties:
        message:
          type: string
          title: Message
          description: >-
            Human-readable summary. Do not parse programmatically — branch on
            `type`.
        type:
          type: string
          const: unauthorized
          title: Type
          default: unauthorized
      additionalProperties: false
      type: object
      required:
        - message
      title: UnauthorizedPayload
    NotFoundPayload:
      properties:
        message:
          type: string
          title: Message
          description: >-
            Human-readable summary. Do not parse programmatically — branch on
            `type`.
        type:
          type: string
          const: not_found
          title: Type
          default: not_found
      additionalProperties: false
      type: object
      required:
        - message
      title: NotFoundPayload
    InternalErrorPayload:
      properties:
        message:
          type: string
          title: Message
          description: >-
            Human-readable summary. Do not parse programmatically — branch on
            `type`.
        type:
          type: string
          const: internal_error
          title: Type
          default: internal_error
      additionalProperties: false
      type: object
      required:
        - message
      title: InternalErrorPayload
    PhoneNumberBlockedPayload:
      properties:
        message:
          type: string
          title: Message
          description: >-
            Human-readable summary. Do not parse programmatically — branch on
            `type`.
        type:
          type: string
          const: phone_number_blocked
          title: Type
          default: phone_number_blocked
        phone_number:
          type: string
          title: Phone Number
          description: The phone number that is blocked.
      additionalProperties: false
      type: object
      required:
        - message
        - phone_number
      title: PhoneNumberBlockedPayload
    CallLimitExceededPayload:
      properties:
        message:
          type: string
          title: Message
          description: >-
            Human-readable summary. Do not parse programmatically — branch on
            `type`.
        type:
          type: string
          const: call_limit_exceeded
          title: Type
          default: call_limit_exceeded
        phone_number:
          type: string
          title: Phone Number
          description: The phone number that hit the limit.
        call_limit:
          type: integer
          title: Call Limit
          description: The per-number call limit that was reached.
      additionalProperties: false
      type: object
      required:
        - message
        - phone_number
        - call_limit
      title: CallLimitExceededPayload
    OutboundCallFailedPayload:
      properties:
        message:
          type: string
          title: Message
          description: >-
            Human-readable summary. Do not parse programmatically — branch on
            `type`.
        type:
          type: string
          const: outbound_call_failed
          title: Type
          default: outbound_call_failed
        reason:
          type: string
          title: Reason
          description: Stable-ish reason string from the call service.
      additionalProperties: false
      type: object
      required:
        - message
        - reason
      title: OutboundCallFailedPayload
    ScenarioNotFoundPayload:
      properties:
        message:
          type: string
          title: Message
          description: >-
            Human-readable summary. Do not parse programmatically — branch on
            `type`.
        type:
          type: string
          const: scenario_not_found
          title: Type
          default: scenario_not_found
        scenario_id:
          type: string
          title: Scenario Id
      additionalProperties: false
      type: object
      required:
        - message
        - scenario_id
      title: ScenarioNotFoundPayload
    ScenarioForbiddenPayload:
      properties:
        message:
          type: string
          title: Message
          description: >-
            Human-readable summary. Do not parse programmatically — branch on
            `type`.
        type:
          type: string
          const: scenario_forbidden
          title: Type
          default: scenario_forbidden
        scenario_id:
          type: string
          title: Scenario Id
      additionalProperties: false
      type: object
      required:
        - message
        - scenario_id
      title: ScenarioForbiddenPayload
    ScenarioInvalidConfigPayload:
      properties:
        message:
          type: string
          title: Message
          description: >-
            Human-readable summary. Do not parse programmatically — branch on
            `type`.
        type:
          type: string
          const: scenario_invalid_config
          title: Type
          default: scenario_invalid_config
        scenario_id:
          type: string
          title: Scenario Id
      additionalProperties: false
      type: object
      required:
        - message
        - scenario_id
      title: ScenarioInvalidConfigPayload
    NoOrganizationPayload:
      properties:
        message:
          type: string
          title: Message
          description: >-
            Human-readable summary. Do not parse programmatically — branch on
            `type`.
        type:
          type: string
          const: no_organization
          title: Type
          default: no_organization
      additionalProperties: false
      type: object
      required:
        - message
      title: NoOrganizationPayload
    CallNotFoundPayload:
      properties:
        message:
          type: string
          title: Message
          description: >-
            Human-readable summary. Do not parse programmatically — branch on
            `type`.
        type:
          type: string
          const: call_not_found
          title: Type
          default: call_not_found
        call_id:
          type: string
          title: Call Id
      additionalProperties: false
      type: object
      required:
        - message
        - call_id
      title: CallNotFoundPayload
    OauthInvalidRedirectUriPayload:
      properties:
        message:
          type: string
          title: Message
          description: >-
            Human-readable summary. Do not parse programmatically — branch on
            `type`.
        type:
          type: string
          const: oauth_invalid_redirect_uri
          title: Type
          default: oauth_invalid_redirect_uri
        redirect_uri:
          type: string
          title: Redirect Uri
      additionalProperties: false
      type: object
      required:
        - message
        - redirect_uri
      title: OauthInvalidRedirectUriPayload
    SchedulingDisabledPayload:
      properties:
        message:
          type: string
          title: Message
          description: >-
            Human-readable summary. Do not parse programmatically — branch on
            `type`.
        type:
          type: string
          const: scheduling_disabled
          title: Type
          default: scheduling_disabled
      additionalProperties: false
      type: object
      required:
        - message
      title: SchedulingDisabledPayload
    InvalidScheduleTimePayload:
      properties:
        message:
          type: string
          title: Message
          description: >-
            Human-readable summary. Do not parse programmatically — branch on
            `type`.
        type:
          type: string
          const: invalid_schedule_time
          title: Type
          default: invalid_schedule_time
      additionalProperties: false
      type: object
      required:
        - message
      title: InvalidScheduleTimePayload
    ScheduleConfigNotFoundPayload:
      properties:
        message:
          type: string
          title: Message
          description: >-
            Human-readable summary. Do not parse programmatically — branch on
            `type`.
        type:
          type: string
          const: schedule_config_not_found
          title: Type
          default: schedule_config_not_found
        schedule_config_id:
          type: string
          title: Schedule Config Id
      additionalProperties: false
      type: object
      required:
        - message
        - schedule_config_id
      title: ScheduleConfigNotFoundPayload
    CallNotPendingPayload:
      properties:
        message:
          type: string
          title: Message
          description: >-
            Human-readable summary. Do not parse programmatically — branch on
            `type`.
        type:
          type: string
          const: call_not_pending
          title: Type
          default: call_not_pending
        status:
          anyOf:
            - type: string
            - type: 'null'
          title: Status
      additionalProperties: false
      type: object
      required:
        - message
        - status
      title: CallNotPendingPayload
    TimeEdge:
      properties:
        hour:
          type: integer
          maximum: 23
          minimum: 0
          title: Hour
        minute:
          type: integer
          maximum: 59
          minimum: 0
          title: Minute
      additionalProperties: false
      type: object
      required:
        - hour
        - minute
      title: TimeEdge
    FieldViolation:
      properties:
        field:
          type: string
          title: Field
          description: >-
            Dot-separated path to the invalid field (e.g.
            `phone_number.country_code`).
          examples:
            - phone_number.country_code
        message:
          type: string
          title: Message
          description: Human-readable description of the violation.
          examples:
            - Must start with +
      additionalProperties: false
      type: object
      required:
        - field
        - message
      title: FieldViolation
  securitySchemes:
    ApiKeyAuth:
      type: http
      scheme: bearer
      description: >-
        API key from your Sarj.ai dashboard. Pass as: Authorization: Bearer
        <api-key>

````