

```json
{
  "openapi": "3.0.0",
  "info": {
    "title": "Scheduler Admin API",
    "version": "1.0",
    "contact": {
      "name": "#livegames-devs"
    },
    "description": "# Introduction\nThis is the admin client API specification for the Unity Scheduler service.  The Scheduler service is responsible for scheduling events to be sent to the Triggers service.\n## Rate Limits\nThe API has rate limiting in place. Request are limited on a per-user basis to 600 requests per minute which would allow for a sustained 10 requests per second.\nThe List endpoint is limited to 120 requests per minute, which allows for sustained 2 requests per second.\nThe API responds with a `429` HTTP status code if the rate limit is exceeded.\nIt will also respond with a `Retry-After` header to be used in conjunction with a client's retry logic. The value is the number of seconds until a request for the given player will be accepted.\n"
  },
  "tags": [
    {
      "name": "Scheduler",
      "description": "Endpoints associated with the Scheduler service"
    }
  ],
  "servers": [
    {
      "url": "https://services.api.unity.com",
      "description": "Prd"
    },
    {
      "url": "https://staging.services.api.unity.com",
      "description": "Stg"
    },
    {
      "url": "https://localhost",
      "description": "Dev"
    }
  ],
  "paths": {
    "/scheduler/v1/projects/{projectId}/environments/{environmentId}/configs": {
      "parameters": [
        {
          "$ref": "#/components/parameters/projectId.v1"
        },
        {
          "$ref": "#/components/parameters/environmentId.v1"
        }
      ],
      "get": {
        "summary": "List Scheduler Configs",
        "security": [
          {
            "ServiceAccount": [
              "scheduler.configs.list"
            ]
          }
        ],
        "tags": [
          "Scheduler"
        ],
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 1000
            },
            "description": "The number of schedules to display per page"
          },
          {
            "in": "query",
            "name": "after",
            "schema": {
              "type": "string",
              "default": null,
              "nullable": true
            },
            "description": "A token to get the next page"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SchedulerConfigPage"
                },
                "examples": {
                  "Success": {
                    "value": {
                      "after": "eyJTZWFyY2hBZnRlciI6WzAsMSwyMl0sIlNjcm9sbElEIjoiIiwiUG9pbnRJblRpbWVJRCI6IjAwMCJ9=",
                      "configs": [
                        {
                          "id": "00000000-0000-0000-0000-000000000001",
                          "name": "Example Recurring",
                          "eventName": "example-event",
                          "type": "recurring",
                          "schedule": "0 * * * *",
                          "payloadVersion": 1,
                          "payload": "{}"
                        },
                        {
                          "id": "00000000-0000-0000-0000-000000000002",
                          "name": "Example One Time",
                          "eventName": "example-event",
                          "type": "one-time",
                          "schedule": "2023-10-02T15:00:00Z",
                          "payloadVersion": 1,
                          "payload": "{}"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "listSchedulerConfigs",
        "description": "Get list of schedules for the given project and environment"
      },
      "post": {
        "summary": "Create Schedule Config",
        "security": [
          {
            "ServiceAccount": [
              "scheduler.configs.create"
            ]
          }
        ],
        "tags": [
          "Scheduler"
        ],
        "operationId": "createScheduleConfig",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduleConfigId"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "description": "Add schedule to project environment",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScheduleConfigBody"
              },
              "examples": {
                "Recurring": {
                  "value": {
                    "name": "Example Recurring",
                    "eventName": "example-event",
                    "type": "recurring",
                    "schedule": "0 * * * *",
                    "payloadVersion": 1,
                    "payload": "{}"
                  }
                },
                "OneTime": {
                  "value": {
                    "name": "Example One Time",
                    "eventName": "example-event",
                    "type": "one-time",
                    "schedule": "2023-10-02T15:00:00Z",
                    "payloadVersion": 1,
                    "payload": "{}"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/scheduler/v1/projects/{projectId}/environments/{environmentId}/configs:batch-delete": {
      "parameters": [
        {
          "$ref": "#/components/parameters/projectId.v1"
        },
        {
          "$ref": "#/components/parameters/environmentId.v1"
        }
      ],
      "post": {
        "summary": "Delete Schedule Configs",
        "security": [
          {
            "ServiceAccount": [
              "scheduler.configs.delete"
            ]
          }
        ],
        "tags": [
          "Scheduler"
        ],
        "operationId": "deleteScheduleConfigs",
        "responses": {
          "200": {
            "description": "Failure",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchDeleteFailedResponse"
                }
              }
            }
          },
          "204": {
            "description": "No Content"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "description": "Deletes multiple schedule configurations",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "minItems": 1,
                "maxItems": 100,
                "uniqueItems": true,
                "items": {
                  "type": "string"
                }
              },
              "examples": {
                "Batch": {
                  "value": [
                    "00000000-0000-0000-0000-000000000001",
                    "00000000-0000-0000-0000-000000000002"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/scheduler/v1/projects/{projectId}/environments/{environmentId}/configs/{configId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/projectId.v1"
        },
        {
          "$ref": "#/components/parameters/environmentId.v1"
        },
        {
          "$ref": "#/components/parameters/ConfigId"
        }
      ],
      "get": {
        "summary": "Get Schedule Config",
        "security": [
          {
            "ServiceAccount": [
              "scheduler.configs.get"
            ]
          }
        ],
        "tags": [
          "Scheduler"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduleConfig"
                },
                "examples": {
                  "Success": {
                    "value": {
                      "id": "00000000-0000-0000-0000-000000000001",
                      "name": "Example Recurring Event",
                      "eventName": "example-event",
                      "type": "recurring",
                      "schedule": "0 * * * *",
                      "payloadVersion": 1,
                      "payload": "{}"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "operationId": "getScheduleConfig",
        "description": "Retrieves the configuration for a specific schedule"
      },
      "delete": {
        "summary": "Delete Schedule Config",
        "security": [
          {
            "ServiceAccount": [
              "scheduler.configs.delete"
            ]
          }
        ],
        "tags": [
          "Scheduler"
        ],
        "operationId": "deleteScheduleConfig",
        "responses": {
          "204": {
            "description": "No Content"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "description": "Deletes the configuration for a specific schedule"
      }
    }
  },
  "components": {
    "schemas": {
      "ScheduleName": {
        "type": "string",
        "description": "The display name used to identify a schedule. This must be unique for currently scheduled events.",
        "minLength": 1,
        "maxLength": 255
      },
      "ScheduleEventName": {
        "type": "string",
        "description": "The schedule event name is passed through to the triggers service as part of the event type so that the trigger event is defined as `com.unity.services.scheduler.{scheduleEventName}.v1`\nThe triggers service uses this to identify incoming events and execute the configured action.\nFor a trigger configuration to action an incoming event with type `com.unity.services.scheduler.example-event.v1`, it would require a value of `example-event` to be passed in here.",
        "minLength": 1,
        "maxLength": 255,
        "x-examples": {
          "Example Event": "example-event"
        }
      },
      "ScheduleType": {
        "description": "Defines the type of schedule config. Supported schedule types:\n- recurring\n- one-time",
        "anyOf": [
          {
            "$ref": "#/components/schemas/ScheduleTypeRecurring"
          },
          {
            "$ref": "#/components/schemas/ScheduleTypeOneTime"
          }
        ]
      },
      "ScheduleTypeRecurring": {
        "title": "ScheduleTypeRecurring",
        "type": "string",
        "description": "A schedule config with a type of `recurring` requires the schedule field to have a valid `cron` expression."
      },
      "ScheduleTypeOneTime": {
        "title": "ScheduleTypeOneTime",
        "type": "string",
        "description": "A schedule config with a type of `one-time` requires the schedule field to have a valid RFC3339 timestamp."
      },
      "Schedule": {
        "type": "string",
        "description": "Defines when the planned event should occur.\n\nIf the schedule config has a type of `one-time` this field must have a valid RFC3339 timestamp.\nIf the schedule config has a type of `recurring` this field must have a valid cron expression as per below:\n\nField name   | Allowed values  | Allowed special characters\n----------   | --------------  | --------------------------\nMinutes      | 0-59            | * / , -\nHours        | 0-23            | * / , -\nDay of month | 1-31            | * / , -\nMonth        | 1-12 or JAN-DEC | * / , -\nDay of week  | 0-6 or SUN-SAT  | * / , -\n\nRecurring schedules have a minimum scheduled frequency of once per hour."
      },
      "SchedulePayloadVersion": {
        "type": "integer",
        "minimum": 1
      },
      "SchedulePayload": {
        "type": "string",
        "description": "Defines JSON event payload. Maximum size of 1kb."
      },
      "ScheduleConfigId": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "id"
        ]
      },
      "ScheduleConfigBody": {
        "type": "object",
        "x-examples": {
          "Recurring": {
            "name": "TestSchedule",
            "eventName": "schedule-test",
            "type": "recurring",
            "schedule": "0 * * * *",
            "payloadVersion": 1,
            "payload": "{\"someBoolean\": true, \"someString\": \"schedule-test\"}"
          }
        },
        "properties": {
          "name": {
            "$ref": "#/components/schemas/ScheduleName"
          },
          "eventName": {
            "$ref": "#/components/schemas/ScheduleEventName"
          },
          "type": {
            "$ref": "#/components/schemas/ScheduleType"
          },
          "schedule": {
            "$ref": "#/components/schemas/Schedule"
          },
          "payloadVersion": {
            "$ref": "#/components/schemas/SchedulePayloadVersion"
          },
          "payload": {
            "$ref": "#/components/schemas/SchedulePayload"
          }
        },
        "required": [
          "name",
          "eventName",
          "type",
          "schedule",
          "payloadVersion"
        ]
      },
      "SchedulerConfigPage": {
        "type": "object",
        "x-examples": {
          "Success": {
            "after": "eyJTZWFyY2hBZnRlciI6WzAsMSwyMl0sIlNjcm9sbElEIjoiIiwiUG9pbnRJblRpbWVJRCI6IjAwMCJ9=",
            "configs": [
              {
                "id": "00000000-0000-0000-0000-000000000000",
                "name": "TestSchedule",
                "eventName": "schedule-test",
                "type": "recurring",
                "schedule": "0 * * * *",
                "payloadVersion": 1,
                "payload": "{\"someBoolean\": true, \"someString\": \"schedule-test\"}"
              }
            ]
          }
        },
        "properties": {
          "after": {
            "type": "string"
          },
          "configs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ScheduleConfig"
            }
          }
        }
      },
      "ScheduleConfig": {
        "title": "ScheduleConfig",
        "allOf": [
          {
            "$ref": "#/components/schemas/ScheduleConfigId"
          },
          {
            "$ref": "#/components/schemas/ScheduleConfigBody"
          }
        ],
        "x-examples": {
          "Recurring": {
            "id": "00000000-0000-0000-0000-000000000000",
            "name": "TestSchedule",
            "eventName": "schedule-test",
            "type": "recurring",
            "schedule": "0 * * * *",
            "payloadVersion": 1,
            "payload": "{\"someBoolean\": true, \"someString\": \"schedule-test\"}"
          }
        },
        "description": ""
      },
      "BatchFailure": {
        "type": "object",
        "additionalProperties": {
          "$ref": "#/components/schemas/BasicErrorResponse"
        }
      },
      "BatchDeleteFailedResponse": {
        "title": "BatchDeleteFailedResponse",
        "description": "List of failures mapping schedule config id to it's specific error",
        "type": "object",
        "required": [
          "errors"
        ],
        "properties": {
          "errors": {
            "$ref": "#/components/schemas/BatchFailure"
          }
        },
        "example": {
          "errors": {
            "00000000-0000-0000-0000-000000000001": {
              "type": "problems/basic",
              "title": "Error",
              "status": 400,
              "detail": "Bad request",
              "instance": null,
              "code": 55
            },
            "00000000-0000-0000-0000-000000000002": {
              "type": "problems/basic",
              "title": "Error",
              "status": 503,
              "detail": "Temporary Service Error",
              "instance": null,
              "code": 3
            }
          }
        }
      },
      "BasicErrorResponse": {
        "title": "BasicErrorResponse",
        "description": "See section [3.1. Members of a Problem Details Object](https://www.rfc-editor.org/rfc/rfc7807#section-3.1) in the Internet Engineering Task Force's [Problem Details for HTTP APIs](https://www.rfc-editor.org/rfc/rfc7807).",
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "A URI reference [RFC3986] that identifies the problem type. This specification encourages that, when dereferenced, it provide human-readable documentation for the problem type (for example, using HTML [W3C.REC-html5-20141028]). When this member is not present, its value is assumed to be `about:blank`."
          },
          "title": {
            "type": "string",
            "description": "A short, human-readable summary of the problem type. It should not change from occurrence to occurrence of the problem, except for purposes of localization (for example, using proactive content negotiation; see [RFC7231], Section 3.4)."
          },
          "status": {
            "type": "integer",
            "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem."
          },
          "code": {
            "description": "Service specific error code",
            "type": "integer"
          },
          "detail": {
            "type": "string",
            "description": "A human-readable explanation specific to this occurrence of the problem."
          },
          "instance": {
            "type": "string",
            "nullable": true,
            "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced."
          }
        },
        "required": [
          "type"
        ]
      },
      "ValidationErrorResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/BasicErrorResponse"
          },
          {
            "title": "ValidationErrorResponse",
            "type": "object",
            "description": "Validation error response when a value provided from the client does not pass validation on server.",
            "example": {
              "type": "problems/validation",
              "title": "Validation error",
              "status": 400,
              "code": 55,
              "detail": "See 'errors' for specific validation errors",
              "instance": null,
              "errors": [
                {
                  "field": "string",
                  "messages": [
                    "parameter is required"
                  ]
                }
              ]
            },
            "properties": {
              "errors": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            }
          }
        ],
        "required": [
          "type",
          "title",
          "status",
          "code",
          "detail",
          "errors"
        ]
      },
      "ValidationError": {
        "title": "ValidationError",
        "type": "object",
        "properties": {
          "field": {
            "type": "string"
          },
          "messages": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "field",
          "messages"
        ],
        "description": "Single error in the Validation Error Response."
      },
      "BadRequestErrorResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/BasicErrorResponse"
          },
          {
            "type": "object",
            "title": "BadRequestErrorResponse",
            "example": {
              "type": "problems/basic",
              "title": "Bad Request",
              "status": 400,
              "code": 55,
              "detail": "Failed to parse request body. Error: Unexpected end of JSON input"
            }
          }
        ]
      },
      "UnauthorizedErrorResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/BasicErrorResponse"
          },
          {
            "type": "object",
            "title": "UnauthorizedErrorResponse",
            "example": {
              "type": "problems/basic",
              "title": "Unauthorized",
              "status": 401,
              "code": 53,
              "detail": "Unauthorized"
            }
          }
        ]
      },
      "NotFoundErrorResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/BasicErrorResponse"
          },
          {
            "type": "object",
            "title": "NotFoundErrorResponse",
            "example": {
              "type": "problems/basic",
              "title": "Not Found",
              "status": 404,
              "code": 54,
              "detail": "Schedule config could not be found"
            }
          }
        ]
      },
      "ConflictErrorResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/BasicErrorResponse"
          },
          {
            "type": "object",
            "title": "ConflictErrorResponse",
            "example": {
              "type": "problems/basic",
              "title": "Conflict",
              "status": 409,
              "code": 58,
              "detail": "Schedule already exists with the same name"
            }
          }
        ]
      },
      "TooManyRequestsErrorResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/BasicErrorResponse"
          },
          {
            "type": "object",
            "title": "TooManyRequestsErrorResponse",
            "example": {
              "type": "problems/basic",
              "title": "Too Many Requests",
              "status": 429,
              "code": 50,
              "detail": "Too many requests"
            }
          }
        ]
      },
      "InternalServerErrorResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/BasicErrorResponse"
          },
          {
            "type": "object",
            "title": "InternalServerErrorResponse",
            "example": {
              "type": "problems/basic",
              "title": "Internal Server Error",
              "status": 500,
              "code": 0,
              "detail": "An unknown error occurred"
            }
          }
        ]
      },
      "ServiceUnavailableErrorResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/BasicErrorResponse"
          },
          {
            "type": "object",
            "title": "ServiceUnavailableErrorResponse",
            "example": {
              "type": "problems/basic",
              "title": "Service Unavailable",
              "status": 503,
              "code": 3,
              "detail": "service health ping failed"
            }
          }
        ]
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Bad Request. Returned code indicates one of:\n- Request parameter validation failure\n- Other\nSee the errors field for more details.\n",
        "content": {
          "application/problem+json": {
            "schema": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/BadRequestErrorResponse"
                },
                {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              ],
              "discriminator": {
                "propertyName": "type",
                "mapping": {
                  "problems/basic": "#/components/schemas/BadRequestErrorResponse",
                  "problems/validation": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Invalid Authentication Token",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/UnauthorizedErrorResponse"
            }
          }
        }
      },
      "NotFound": {
        "description": "Not Found",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/NotFoundErrorResponse"
            }
          }
        }
      },
      "Conflict": {
        "description": "Conflict",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ConflictErrorResponse"
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Too Many Requests",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "number"
            },
            "description": "The number of seconds until a request is accepted"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/TooManyRequestsErrorResponse"
            }
          }
        }
      },
      "InternalServerError": {
        "description": "Internal Server Error",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/InternalServerErrorResponse"
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "Service Unavailable",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ServiceUnavailableErrorResponse"
            }
          }
        }
      }
    },
    "parameters": {
      "environmentId.v1": {
        "name": "environmentId",
        "in": "path",
        "description": "The Environment ID of a project",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "projectId.v1": {
        "name": "projectId",
        "in": "path",
        "description": "The project's [Project ID](https://docs.unity.com/en-us/cloud/projects/create-project)",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "ConfigId": {
        "name": "configId",
        "in": "path",
        "description": "ID of the scheduler config. List the scheduler configurations to retrieve IDs.",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        },
        "example": "00000000-0000-0000-0000-000000000000"
      }
    },
    "securitySchemes": {
      "ServiceAccount": {
        "type": "http",
        "scheme": "basic",
        "description": "To get started with Authentication, please visit the [Service Account Authentication section](https://services.docs.unity.com/docs/service-account-auth).\n\nFor this API, you will need to add the following role(s) to your service account :\n\n| Role Type | Role Name | Permissions |\n| --- | --- | --- |\n| Project Level Role | Scheduler Configuration Viewer | <ul><li>scheduler.configs.get</li><li>scheduler.configs.list</li></ul> |\n| Project Level Role | Scheduler Configuration Editor | <ul><li>scheduler.configs.get</li><li>scheduler.configs.list</li><li>scheduler.configs.create</li><li>scheduler.configs.delete</li></ul> |"
      }
    },
    "examples": {}
  }
}
```