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

# Sora-2 - Text To Video

> Flagship sora 2 text to video. Superior cinematic quality and smooth motion for advanced video creators.

## Authentication

1. Sign up for a GPTProto account at [https://gptproto.com](https://gptproto.com)
2. Navigate to the API Keys section in your dashboard
3. Generate a new API key (sk-xxxxx)
4. Copy and securely store your API key
   For authentication details, please refer to the [Authentication](https://docs.gptproto.com/authentication) section.

## Initiate Request

<CodeGroup>
  ```bash cURL theme={null}
  curl --location 'https://gptproto.com/v1/videos' \
  --header 'Authorization: GPTPROTO_API_KEY' \
  --form 'model="sora-2"' \
  --form 'prompt="Put a hat on the cat"'

  ```

  ```javascript JavaScript theme={null}
  const axios = require('axios');
  const FormData = require('form-data');
  let data = new FormData();
  data.append('model', 'sora-2');
  data.append('prompt', 'Put a hat on the cat');

  let config = {
    method: 'post',
    maxBodyLength: Infinity,
    url: 'https://gptproto.com/v1/videos',
    headers: { 
      'Authorization': 'GPTPROTO_API_KEY', 
      ...data.getHeaders()
    },
    data : data
  };

  axios.request(config)
  .then((response) => {
    console.log(JSON.stringify(response.data));
  })
  .catch((error) => {
    console.log(error);
  });


  ```

  ```python Python theme={null}
  import http.client
  import mimetypes
  from codecs import encode

  conn = http.client.HTTPSConnection("gptproto.com")
  dataList = []
  boundary = 'wL36Yn8afVp8Ag7AmP8qZ0SA4n1v9T'
  dataList.append(encode('--' + boundary))
  dataList.append(encode('Content-Disposition: form-data; name=model;'))

  dataList.append(encode('Content-Type: {}'.format('text/plain')))
  dataList.append(encode(''))

  dataList.append(encode("sora-2"))
  dataList.append(encode('--' + boundary))
  dataList.append(encode('Content-Disposition: form-data; name=prompt;'))

  dataList.append(encode('Content-Type: {}'.format('text/plain')))
  dataList.append(encode(''))

  dataList.append(encode("Put a hat on the cat"))
  dataList.append(encode('--'+boundary+'--'))
  dataList.append(encode(''))
  body = b'\r\n'.join(dataList)
  payload = body
  headers = {
    'Authorization': 'GPTPROTO_API_KEY',
    'Content-type': 'multipart/form-data; boundary={}'.format(boundary)
  }
  conn.request("POST", "/v1/videos", payload, headers)
  res = conn.getresponse()
  data = res.read()
  print(data.decode("utf-8"))

  ```

  ```go Go theme={null}
  package main

  import (
    "fmt"
    "bytes"
    "mime/multipart"
    "net/http"
    "io"
  )

  func main() {

    url := "https://gptproto.com/v1/videos"
    method := "POST"

    payload := &bytes.Buffer{}
    writer := multipart.NewWriter(payload)
    _ = writer.WriteField("model", "sora-2")
    _ = writer.WriteField("prompt", "Put a hat on the cat")
    err := writer.Close()
    if err != nil {
      fmt.Println(err)
      return
    }


    client := &http.Client {
    }
    req, err := http.NewRequest(method, url, payload)

    if err != nil {
      fmt.Println(err)
      return
    }
    req.Header.Add("Authorization", "GPTPROTO_API_KEY")

    req.Header.Set("Content-Type", writer.FormDataContentType())
    res, err := client.Do(req)
    if err != nil {
      fmt.Println(err)
      return
    }
    defer res.Body.Close()

    body, err := io.ReadAll(res.Body)
    if err != nil {
      fmt.Println(err)
      return
    }
    fmt.Println(string(body))
  }

  ```
</CodeGroup>

## Query result

### How to obtain the id

After submitting your video generation request to `/v1/videos`, the response will contain the `id` you need for querying results.

### Query Task Status

Retrieve detailed information about the video generation task, including status, progress, and video URL.

<CodeGroup>
  ```bash cURL theme={null}
  curl --location --request GET 'https://gptproto.com/v1/videos/{{id}}' \
  --header 'Authorization: GPTPROTO_API_KEY'
  ```

  ```python Python theme={null}
  import requests
  import json

  url = "https://gptproto.com/v1/videos/{{id}}"
  headers = {
      "Authorization": "GPTPROTO_API_KEY"
  }

  response = requests.get(url, headers=headers)
  result = response.json()
  print(json.dumps(result, indent=2))
  ```

  ```javascript JavaScript theme={null}
  const url = "https://gptproto.com/v1/videos/{{id}}";
  const headers = {
    "Authorization": "GPTPROTO_API_KEY"
  };

  fetch(url, {
    method: "GET",
    headers: headers
  })
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error("Error:", error));
  ```

  ```go Go theme={null}
  package main

  import (
      "encoding/json"
      "fmt"
      "io/ioutil"
      "net/http"
  )

  func main() {
      url := "https://gptproto.com/v1/videos/{{id}}"

      req, _ := http.NewRequest("GET", url, nil)
      req.Header.Set("Authorization", "GPTPROTO_API_KEY")

      client := &http.Client{}
      resp, err := client.Do(req)
      if err != nil {
          panic(err)
      }
      defer resp.Body.Close()

      body, _ := ioutil.ReadAll(resp.Body)
      fmt.Println(string(body))
  }
  ```
</CodeGroup>

**Query Task Status Response:**

```json theme={null}
{
    "id": "video_****",
    "size": "720x1280",
    "error": null,
    "model": "sora-2",
    "object": "video",
    "prompt": "Put a hat on the cat",
    "status": "completed",
    "seconds": "4",
    "progress": 100,
    "created_at": "1770098584",
    "expires_at": "1770184984",
    "completed_at": "1770098708",
    "remixed_from_video_id": null
}
```

### Query Video Content

Directly output the video content for immediate use or download.

<CodeGroup>
  ```bash cURL theme={null}
  curl --location --request GET 'https://gptproto.com/v1/videos/{{id}}/content' \
  --header 'Authorization: GPTPROTO_API_KEY'
  ```

  ```python Python theme={null}
  import requests
  import os

  url = "https://gptproto.com/v1/videos/{{id}}/content"
  headers = {
      "Authorization": "GPTPROTO_API_KEY"
  }

  response = requests.get(url, headers=headers, stream=True)

  if response.status_code == 200:
      with open("video_output.mp4", "wb") as f:
          for chunk in response.iter_content(chunk_size=1024):
              if chunk:
                  f.write(chunk)
      print("Video downloaded successfully")
  else:
      print(f"Failed to download video: {response.status_code}")
  ```

  ```javascript JavaScript theme={null}
  const url = "https://gptproto.com/v1/videos/{{id}}/content";
  const headers = {
    "Authorization": "GPTPROTO_API_KEY"
  };

  fetch(url, {
    method: "GET",
    headers: headers
  })
    .then(response => response.blob())
    .then(blob => {
      const url = window.URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = 'video_output.mp4';
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      window.URL.revokeObjectURL(url);
    })
    .catch(error => console.error("Error:", error));
  ```

  ```go Go theme={null}
  package main

  import (
      "fmt"
      "io"
      "net/http"
      "os"
  )

  func main() {
      url := "https://gptproto.com/v1/videos/{{id}}/content"
      req, _ := http.NewRequest("GET", url, nil)
      req.Header.Set("Authorization", "GPTPROTO_API_KEY")

      client := &http.Client{}
      resp, err := client.Do(req)
      if err != nil {
          panic(err)
      }
      defer resp.Body.Close()

      if resp.StatusCode == 200 {
          out, err := os.Create("video_output.mp4")
          if err != nil {
              panic(err)
          }
          defer out.Close()

          _, err = io.Copy(out, resp.Body)
          if err != nil {
              panic(err)
          }

          fmt.Println("Video downloaded successfully")
      } else {
          fmt.Printf("Failed to download video: %d\n", resp.StatusCode)
      }
  }
  ```
</CodeGroup>

## Parameters

| Parameter         | Type   | Required | Default    | Range                                                        | Description                                                                                                                                  |
| ----------------- | ------ | -------- | ---------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `prompt`          | string | ✅ Yes    | -          | -                                                            | Text prompt that describes the video to generate.                                                                                            |
| `input_reference` | file   | ❌ No     | -          | -                                                            | Optional image reference that guides generation.                                                                                             |
| `model`           | string | ❌ No     | `sora-2`   | `sora-2`<br />`sora-2-pro`                                   | The video generation model to use. Defaults to `sora-2`.                                                                                     |
| `seconds`         | string | ❌ No     | `4`        | `4`<br />`8`<br />`12`                                       | Clip duration in seconds. Defaults to 4 seconds.                                                                                             |
| `size`            | string | ❌ No     | `720x1280` | `720x1280`<br />`1280x720`<br />`1024x1792`<br />`1792x1024` | Output resolution formatted as width x height. Defaults to 720x1280.Note: `1024x1792` and `1792x1024` are only supported by sora2-pro model. |

## Error Codes

### Common Error Codes

| Error Code | Error Name               | Description                                                                                                       |
| ---------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------- |
| 401        | Unauthorized             | API key is missing or invalid                                                                                     |
| 403        | Forbidden                | Your API key doesn't have permission to access this resource, or insufficient balance for the requested operation |
| 429        | Too Many Requests        | You've exceeded your rate limit                                                                                   |
| 500        | Internal server error    | An internal server error occurred                                                                                 |
| 503        | Content policy violation | Content blocked due to safety concerns (actual status code is 400)                                                |
