{
    "openapi": "3.1.0",
    "info": {
        "title": "The Arles API",
        "summary": "Make pictures from a prompt, and fetch them when they are ready.",
        "description": "Every request carries a token: `Authorization: Bearer <token>`. You make yours on your settings screen in Arles, it is shown once, and making a second one replaces the first. The share endpoints under `/api/v1/public` are the exception: a share link is public, so they take no token and are counted by address.\n\nAsking for a round answers straight away with the round, not with a picture. Ask about the round again until it says done, then fetch its images. About once a second is right.\n\nYou reach your own work and nothing else. Somebody else's round or picture answers 404, never 403. A share endpoint serves what the link serves and nothing more, and no endpoint ever says who voted for a picture, only how many did.\n\nTwo hundred requests every thirty seconds per token. Every answer carries `X-RateLimit-Limit` and `X-RateLimit-Remaining`, so a loop can pace itself without counting, and a 429 carries `Retry-After`. Your role sets the best quality and the largest number of images one round may ask for, and the service clamps whatever you send to it rather than refusing.\n\nErrors are JSON with a `message`. 401 means the token is missing or no longer good, 404 means it is not there or not yours, 422 means the request was wrong, 429 means too many requests.",
        "version": "1.0.0"
    },
    "servers": [
        {
            "url": "https://arles.hu"
        }
    ],
    "components": {
        "securitySchemes": {
            "bearerAuth": {
                "type": "http",
                "scheme": "bearer"
            }
        }
    },
    "security": [
        {
            "bearerAuth": []
        }
    ],
    "paths": {
        "/api/v1/me": {
            "get": {
                "summary": "Who the token belongs to",
                "description": "The account behind the token, its role, and what a round of yours may ask for. Ask this first. It tells you the ceilings the service will clamp your round to, so you do not have to guess them.",
                "operationId": "whoTheTokenBelongsTo",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The account, its role, the best quality and the largest number of images one round may ask for, every quality name there is, and what has been spent so far."
                    },
                    "401": {
                        "description": "The token is missing or no longer good."
                    },
                    "404": {
                        "description": "Not there, or not yours."
                    },
                    "429": {
                        "description": "More than two hundred requests in thirty seconds."
                    }
                }
            }
        },
        "/api/v1/sessions": {
            "get": {
                "summary": "Your sessions",
                "description": "Every session of yours, most recently used first. A session is one piece of work and holds the rounds that belong to it. Use this to find the id to send with a round, so related work stays together.",
                "operationId": "yourSessions",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A list of sessions with an id, a name, how many rounds each holds and when it was last used."
                    },
                    "401": {
                        "description": "The token is missing or no longer good."
                    },
                    "404": {
                        "description": "Not there, or not yours."
                    },
                    "429": {
                        "description": "More than two hundred requests in thirty seconds."
                    }
                }
            },
            "post": {
                "summary": "Start a session",
                "description": "Make a session with a name of your choosing. Optional. A round sent with no session makes one, and a language model names it from the first prompt.",
                "operationId": "startASession",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "201": {
                        "description": "The session."
                    },
                    "401": {
                        "description": "The token is missing or no longer good."
                    },
                    "404": {
                        "description": "Not there, or not yours."
                    },
                    "422": {
                        "description": "The request was wrong. The message says how."
                    },
                    "429": {
                        "description": "More than two hundred requests in thirty seconds."
                    }
                },
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "description": "What to call it. Left out, it is named for you."
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/v1/sessions/{session}/rounds": {
            "get": {
                "summary": "The rounds in a session",
                "description": "Every round in one session of yours, most recent first, a page at a time. This is how you find work you made earlier without having kept the ids. A page holds twenty five rounds unless you ask for another number, and the answer carries the usual links and meta so you can walk through the rest.",
                "operationId": "theRoundsInASession",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of rounds, each shaped as one round is, with the images it has made."
                    },
                    "401": {
                        "description": "The token is missing or no longer good."
                    },
                    "404": {
                        "description": "Not there, or not yours."
                    },
                    "429": {
                        "description": "More than two hundred requests in thirty seconds."
                    }
                },
                "parameters": [
                    {
                        "name": "session",
                        "in": "path",
                        "required": true,
                        "description": "The session id, from your sessions.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "required": false,
                        "description": "How many rounds one page holds, between 1 and 100. Left out, twenty five.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ]
            }
        },
        "/api/v1/sessions/{session}/voted-images": {
            "get": {
                "summary": "What people voted for",
                "description": "The pictures in one session of yours that got votes on its shared page, most votes first. Pictures nobody voted for are left out. Each picture carries `votes` and `round`: the id, number and prompt of the round that made it, and where to ask for the whole round. Only counts are given, never who voted. Votes belong to the picture, so they are here whether or not the session is still shared.",
                "operationId": "whatPeopleVotedFor",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A list of pictures with their vote counts and their rounds."
                    },
                    "401": {
                        "description": "The token is missing or no longer good."
                    },
                    "404": {
                        "description": "Not there, or not yours."
                    },
                    "429": {
                        "description": "More than two hundred requests in thirty seconds."
                    }
                },
                "parameters": [
                    {
                        "name": "session",
                        "in": "path",
                        "required": true,
                        "description": "The session id, from your sessions.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ]
            }
        },
        "/api/v1/rounds": {
            "post": {
                "summary": "Make images",
                "description": "Ask for a round. The prompt is the only thing you must send. A round is queued and answered at once with its id: making an image takes about ten seconds and the image service does one at a time, so nothing here waits for a picture. Ask for the round again to see how it is getting on.",
                "operationId": "makeImages",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "202": {
                        "description": "202 with the round, its session, and where to ask about it."
                    },
                    "401": {
                        "description": "The token is missing or no longer good."
                    },
                    "404": {
                        "description": "Not there, or not yours."
                    },
                    "422": {
                        "description": "The request was wrong. The message says how."
                    },
                    "429": {
                        "description": "More than two hundred requests in thirty seconds."
                    }
                },
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "prompt"
                                ],
                                "properties": {
                                    "prompt": {
                                        "type": "string",
                                        "description": "What you want a picture of, in prose. 100 to 200 words reads best."
                                    },
                                    "quality": {
                                        "type": "string",
                                        "description": "How much work goes into each image: Draft, Normal, Fine or Best. Left out, Normal is used. Clamped to what your role allows. A step count is not accepted: what one is worth belongs to the checkpoint the image service has loaded, and that changes."
                                    },
                                    "images": {
                                        "type": "integer",
                                        "description": "How many pictures this round makes. Left out, the default is used. Clamped to what your role allows."
                                    },
                                    "size": {
                                        "type": "string",
                                        "description": "The shape of the picture, width x height: 1024x1024, 1328x768, 768x1328, 864x1344, 1328x1328. 864x1344 is 9:14, the shape of a playing card. Left out, 1024x1024 is used. Any other value is refused with 422."
                                    },
                                    "session": {
                                        "type": "integer",
                                        "description": "The session to put it in. Left out, one is made."
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/v1/rounds/{round}": {
            "get": {
                "summary": "How a round is getting on",
                "description": "The state of one round and the pictures it has made so far. Queued, running, done, failed or cancelled. The images arrive one at a time, so this can answer with some of them while the round is still running. While a round is unfinished it also carries `queue_position`, how many rounds are in front of it, and `estimated_wait_seconds`, roughly how long until it has made its last image. Both are null once it is finished. Poll on the wait rather than every second: the estimate is arithmetic at about ten seconds an image and does not know that a service which has been idle spends about two minutes forty loading its weights first.",
                "operationId": "howARoundIsGettingOn",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The round, its state, where it stands in the queue, what it has cost, and every image it has made with a link to each and its vote count."
                    },
                    "401": {
                        "description": "The token is missing or no longer good."
                    },
                    "404": {
                        "description": "Not there, or not yours."
                    },
                    "429": {
                        "description": "More than two hundred requests in thirty seconds."
                    }
                },
                "parameters": [
                    {
                        "name": "round",
                        "in": "path",
                        "required": true,
                        "description": "The id you were given.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ]
            },
            "delete": {
                "summary": "Delete a round",
                "description": "The round and every picture it made, files included. Refused with 409 while the round is queued or running, and when other rounds were continued from it. The refusal carries `children`, the ids of those rounds: delete them first. Deleting cannot be undone.",
                "operationId": "deleteARound",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "204": {
                        "description": "204 with no body."
                    },
                    "401": {
                        "description": "The token is missing or no longer good."
                    },
                    "404": {
                        "description": "Not there, or not yours."
                    },
                    "409": {
                        "description": "The round is still open, or other rounds came from it. The message says which."
                    },
                    "429": {
                        "description": "More than two hundred requests in thirty seconds."
                    }
                },
                "parameters": [
                    {
                        "name": "round",
                        "in": "path",
                        "required": true,
                        "description": "The id you were given.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ]
            }
        },
        "/api/v1/rounds/{round}/cancel": {
            "post": {
                "summary": "Cancel a round",
                "description": "Stop a round that is still waiting in the queue. Only a queued round can be cancelled: once the image service has started on it, it cannot be interrupted. A running or finished round is refused with 409, and the refusal carries its `status`. Cancelling a round that is already cancelled answers as if it had just been. A cancelled round can then be deleted.",
                "operationId": "cancelARound",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The round, now cancelled."
                    },
                    "401": {
                        "description": "The token is missing or no longer good."
                    },
                    "404": {
                        "description": "Not there, or not yours."
                    },
                    "409": {
                        "description": "The round has started or has finished. Its status says which."
                    },
                    "429": {
                        "description": "More than two hundred requests in thirty seconds."
                    }
                },
                "parameters": [
                    {
                        "name": "round",
                        "in": "path",
                        "required": true,
                        "description": "The id you were given.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ]
            }
        },
        "/api/v1/public/shares/{share}": {
            "get": {
                "summary": "What a share link holds",
                "description": "The folder or session behind a share link: which of the two it is, its name, and how many pictures it holds. No token. A share link is public, so these four endpoints are too, and they are counted by address rather than by token. They give what the link gives and nothing more: a uuid that names nothing, or something no longer shared, answers 404, and holding a token for the account that shared it changes none of that.",
                "operationId": "whatAShareLinkHolds",
                "security": [],
                "responses": {
                    "200": {
                        "description": "`kind`, folder or session, `name`, and `image_count`."
                    },
                    "404": {
                        "description": "Not there, or not yours."
                    },
                    "429": {
                        "description": "More than two hundred requests in thirty seconds."
                    }
                },
                "parameters": [
                    {
                        "name": "share",
                        "in": "path",
                        "required": true,
                        "description": "The uuid from the share link, the same one /shared/{uuid} opens.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ]
            }
        },
        "/api/v1/public/shares/{share}/images": {
            "get": {
                "summary": "The pictures a share link holds",
                "description": "The pictures behind a share link, a page at a time, in either of the two orders the shared page offers. No token. Each picture carries its size, its vote count and where to fetch its bytes, and those links are the share's own: they need no token either. `sort=order` is the order the folder or session itself has. `sort=votes` is the upvoted ones, most votes first, and pictures nobody voted for are left out, exactly as the shared page reads it. Only counts are given, never who voted.",
                "operationId": "thePicturesAShareLinkHolds",
                "security": [],
                "responses": {
                    "200": {
                        "description": "A page of pictures with the usual links and meta."
                    },
                    "404": {
                        "description": "Not there, or not yours."
                    },
                    "429": {
                        "description": "More than two hundred requests in thirty seconds."
                    }
                },
                "parameters": [
                    {
                        "name": "share",
                        "in": "path",
                        "required": true,
                        "description": "The uuid from the share link.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "sort",
                        "in": "query",
                        "required": false,
                        "description": "`order` or `votes`. Left out, `order`.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "required": false,
                        "description": "How many pictures one page holds, between 1 and 100. Left out, 60.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ]
            }
        },
        "/api/v1/public/shares/{share}/images/{image}": {
            "get": {
                "summary": "One picture from a share link",
                "description": "The PNG itself, for a picture the link holds. No token. The bytes, not a link to them. Add /thumbnail for a small one. A picture that is not in what this link shared answers 404, whoever is asking.",
                "operationId": "onePictureFromAShareLink",
                "security": [],
                "responses": {
                    "200": {
                        "description": "image/png."
                    },
                    "404": {
                        "description": "Not there, or not yours."
                    },
                    "429": {
                        "description": "More than two hundred requests in thirty seconds."
                    }
                },
                "parameters": [
                    {
                        "name": "share",
                        "in": "path",
                        "required": true,
                        "description": "The uuid from the share link.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "image",
                        "in": "path",
                        "required": true,
                        "description": "The id from the list of pictures.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ]
            }
        },
        "/api/v1/images/{image}": {
            "get": {
                "summary": "One picture",
                "description": "The PNG itself. The bytes, not a link to them. Add /thumbnail for a small one.",
                "operationId": "onePicture",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "image/png."
                    },
                    "401": {
                        "description": "The token is missing or no longer good."
                    },
                    "404": {
                        "description": "Not there, or not yours."
                    },
                    "429": {
                        "description": "More than two hundred requests in thirty seconds."
                    }
                },
                "parameters": [
                    {
                        "name": "image",
                        "in": "path",
                        "required": true,
                        "description": "The id from a round.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                ]
            }
        }
    }
}