{
  "openapi": "3.1.0",
  "info": {
    "title": "Daydream Music Generator API",
    "version": "1.0.0",
    "description": "Describe a song, get it back as an MP3 and a WAV. Royalty-free: use it in commercial games and videos. Every account has a monthly number of songs (Free 10, Songs plan 1,000); there are no credits. Docs and examples: https://gen.daydream.live/docs."
  },
  "servers": [
    {
      "url": "https://gen.daydream.live/v1"
    }
  ],
  "security": [
    {
      "bearer": []
    }
  ],
  "paths": {
    "/songs": {
      "post": {
        "operationId": "createSong",
        "summary": "Make a song",
        "description": "Puts the song in line and returns it at once, status queued. Poll GET /songs/{id} every 2 seconds until status is done or failed. Counts one song against the month (given back if it fails).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "prompt"
                ],
                "properties": {
                  "prompt": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 400,
                    "description": "What the song is, in words. Instrumental only: words asking for vocals or lyrics are dropped. Artist names are refused."
                  },
                  "duration": {
                    "type": "number",
                    "minimum": 10,
                    "maximum": 120,
                    "default": 120,
                    "description": "Seconds. Trimmed to whole bars with a short fade out (none when loop is on)."
                  },
                  "bpm": {
                    "type": "integer",
                    "minimum": 60,
                    "maximum": 200,
                    "description": "Default: a tempo the words name, else the genre's usual one, else 100."
                  },
                  "key": {
                    "type": "string",
                    "description": "One of the 24 major and minor keys, e.g. \"C major\", \"A minor\". Default: none."
                  },
                  "loop": {
                    "type": "boolean",
                    "default": false,
                    "description": "Make it a seamless loop: 8 bars unless duration says otherwise, in whole bars, no fade."
                  },
                  "seed": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 2147483647,
                    "description": "Default: random. The same seed and settings make the same song."
                  },
                  "variations": {
                    "type": "integer",
                    "enum": [
                      1,
                      2
                    ],
                    "default": 1,
                    "description": "How many versions. Either way it counts as one song."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "The song, in line.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "status",
                    "prompt",
                    "duration",
                    "bpm",
                    "seed",
                    "variations",
                    "created_at",
                    "takes"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The song's id.",
                      "examples": [
                        "sng_4hT2kq9XbV1nLm0pQe3rZa"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "queued",
                        "rendering",
                        "done",
                        "failed"
                      ],
                      "description": "Where it is: in line, being made, ready, or failed."
                    },
                    "position": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "Place in line while queued (1 is next), else null."
                    },
                    "prompt": {
                      "type": "string"
                    },
                    "duration": {
                      "type": "number",
                      "description": "The length asked for, in seconds."
                    },
                    "bpm": {
                      "type": "integer"
                    },
                    "key": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "loop": {
                      "type": "boolean"
                    },
                    "seed": {
                      "type": "integer"
                    },
                    "variations": {
                      "type": "integer",
                      "enum": [
                        1,
                        2
                      ]
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "finished_at": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "error": {
                      "oneOf": [
                        {
                          "type": "null"
                        },
                        {
                          "$ref": "#/components/schemas/Error"
                        }
                      ]
                    },
                    "takes": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Take"
                      },
                      "description": "One per variation once done; empty until then."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "A field is invalid (the message names it).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No key, or a key that doesn't work.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "This month's songs are used up.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Error"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "limit": {
                          "type": "integer"
                        },
                        "used": {
                          "type": "integer"
                        },
                        "plan": {
                          "type": "string"
                        },
                        "upgrade_url": {
                          "type": "string",
                          "format": "uri"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "422": {
            "description": "The prompt was refused (an artist's name).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 3 of your songs are already in line or being made.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "The generator is unavailable; try again shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listSongs",
        "summary": "Your songs, newest first",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "next_cursor from the last page."
          }
        ],
        "responses": {
          "200": {
            "description": "A page of songs.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "songs",
                    "next_cursor"
                  ],
                  "properties": {
                    "songs": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Song"
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No key, or a key that doesn't work.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/songs/{id}": {
      "get": {
        "operationId": "getSong",
        "summary": "A song: its status, place in line and files",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The song.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "status",
                    "prompt",
                    "duration",
                    "bpm",
                    "seed",
                    "variations",
                    "created_at",
                    "takes"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The song's id.",
                      "examples": [
                        "sng_4hT2kq9XbV1nLm0pQe3rZa"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "queued",
                        "rendering",
                        "done",
                        "failed"
                      ],
                      "description": "Where it is: in line, being made, ready, or failed."
                    },
                    "position": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "Place in line while queued (1 is next), else null."
                    },
                    "prompt": {
                      "type": "string"
                    },
                    "duration": {
                      "type": "number",
                      "description": "The length asked for, in seconds."
                    },
                    "bpm": {
                      "type": "integer"
                    },
                    "key": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "loop": {
                      "type": "boolean"
                    },
                    "seed": {
                      "type": "integer"
                    },
                    "variations": {
                      "type": "integer",
                      "enum": [
                        1,
                        2
                      ]
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "finished_at": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "error": {
                      "oneOf": [
                        {
                          "type": "null"
                        },
                        {
                          "$ref": "#/components/schemas/Error"
                        }
                      ]
                    },
                    "takes": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Take"
                      },
                      "description": "One per variation once done; empty until then."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No key, or a key that doesn't work.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such song on this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/songs/{id}/{n}.mp3": {
      "get": {
        "operationId": "getSongMp3",
        "summary": "A version's MP3 (no auth)",
        "security": [],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "n",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "enum": [
                1,
                2
              ]
            }
          }
        ],
        "responses": {
          "302": {
            "description": "Redirects to the file (a short-lived signed link). The link itself is stable: store it, load it from a game engine."
          },
          "404": {
            "description": "No such file.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/songs/{id}/{n}.wav": {
      "get": {
        "operationId": "getSongWav",
        "summary": "A version's WAV (no auth)",
        "security": [],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "n",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "enum": [
                1,
                2
              ]
            }
          }
        ],
        "responses": {
          "302": {
            "description": "Redirects to the file."
          },
          "404": {
            "description": "No such file.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/usage": {
      "get": {
        "operationId": "getUsage",
        "summary": "Songs used and left this month",
        "responses": {
          "200": {
            "description": "This month's songs.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "plan",
                    "limit",
                    "used",
                    "resets_at"
                  ],
                  "properties": {
                    "plan": {
                      "type": "string",
                      "enum": [
                        "anonymous",
                        "free",
                        "songs",
                        "pro",
                        "max",
                        "internal"
                      ]
                    },
                    "limit": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "Songs a month; null when unlimited."
                    },
                    "used": {
                      "type": "integer"
                    },
                    "resets_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "The first of next month, UTC."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No key, or a key that doesn't work.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "A Daydream API key: https://app.daydream.live/dashboard/api-keys"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error",
          "message"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "A code to branch on."
          },
          "message": {
            "type": "string",
            "description": "What went wrong, in plain words."
          }
        }
      },
      "Song": {
        "type": "object",
        "required": [
          "id",
          "status",
          "prompt",
          "duration",
          "bpm",
          "seed",
          "variations",
          "created_at",
          "takes"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The song's id.",
            "examples": [
              "sng_4hT2kq9XbV1nLm0pQe3rZa"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "rendering",
              "done",
              "failed"
            ],
            "description": "Where it is: in line, being made, ready, or failed."
          },
          "position": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Place in line while queued (1 is next), else null."
          },
          "prompt": {
            "type": "string"
          },
          "duration": {
            "type": "number",
            "description": "The length asked for, in seconds."
          },
          "bpm": {
            "type": "integer"
          },
          "key": {
            "type": [
              "string",
              "null"
            ]
          },
          "loop": {
            "type": "boolean"
          },
          "seed": {
            "type": "integer"
          },
          "variations": {
            "type": "integer",
            "enum": [
              1,
              2
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "finished_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "error": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/Error"
              }
            ]
          },
          "takes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Take"
            },
            "description": "One per variation once done; empty until then."
          }
        }
      },
      "Take": {
        "type": "object",
        "required": [
          "n",
          "seed",
          "duration",
          "waveform",
          "mp3_url",
          "wav_url"
        ],
        "properties": {
          "n": {
            "type": "integer",
            "description": "1 or 2."
          },
          "seed": {
            "type": "integer",
            "description": "The song's seed plus n - 1."
          },
          "duration": {
            "type": "number",
            "description": "Its length in seconds."
          },
          "waveform": {
            "type": "array",
            "items": {
              "type": "number",
              "minimum": 0,
              "maximum": 1
            },
            "description": "Its shape for drawing: 200 peaks from 0 to 1, start to end."
          },
          "mp3_url": {
            "type": "string",
            "format": "uri",
            "description": "MP3, 192 kbps, stereo, 48 kHz. A stable link, no auth: it redirects to the file."
          },
          "wav_url": {
            "type": "string",
            "format": "uri",
            "description": "WAV, 16-bit, stereo, 48 kHz. A stable link, no auth."
          }
        }
      }
    }
  }
}