{
  "info": {
    "name": "mlslabs API",
    "_postman_id": "b7f1c2e4-5a6d-4f8b-9c0e-1d2a3b4c5d6e",
    "description": "REST collections for the mlslabs AI media APIs, plus saved error responses for 401, 402 and 429.\n\nSet the `base_url` and `api_key` collection variables, then send any request. Every failure uses one error envelope: type, code, message, param, request_id, doc_url, retryable and details. Full reference: https://mlslabs.io/docs/errors.html",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "apikey",
    "apikey": [
      {
        "key": "key",
        "value": "X-API-Key",
        "type": "string"
      },
      {
        "key": "value",
        "value": "{{api_key}}",
        "type": "string"
      },
      {
        "key": "in",
        "value": "header",
        "type": "string"
      }
    ]
  },
  "variable": [
    {
      "key": "base_url",
      "value": "https://api.mlslabs.io",
      "type": "string"
    },
    {
      "key": "api_key",
      "value": "",
      "type": "string"
    },
    {
      "key": "job_id",
      "value": "job_01J8ZK3M9QX4HD2N7P",
      "type": "string"
    }
  ],
  "item": [
    {
      "name": "Quickstart",
      "item": [
        {
          "name": "Submit an SDR2HDR job",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-API-Key",
                "value": "{{api_key}}"
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/sdr2hdr/jobs",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "sdr2hdr",
                "jobs"
              ]
            },
            "description": "Long-running work is asynchronous: the response carries a job_id straight away.",
            "auth": {
              "type": "noauth"
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"input\": \"s3://mls-samples/landscape-sdr.mp4\",\n  \"output\": \"s3://mls-outputs/landscape-hdr.mp4\",\n  \"target\": \"hdr10\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "202 · job queued",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "X-API-Key",
                    "value": "{{api_key}}"
                  },
                  {
                    "key": "Idempotency-Key",
                    "value": "{{$guid}}"
                  },
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v1/sdr2hdr/jobs",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v1",
                    "sdr2hdr",
                    "jobs"
                  ]
                },
                "description": "Long-running work is asynchronous: the response carries a job_id straight away.",
                "auth": {
                  "type": "noauth"
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"input\": \"s3://mls-samples/landscape-sdr.mp4\",\n  \"output\": \"s3://mls-outputs/landscape-hdr.mp4\",\n  \"target\": \"hdr10\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Accepted",
              "code": 202,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"job_id\": \"job_01J8ZK3M9QX4HD2N7P\",\n  \"status\": \"queued\",\n  \"estimated_credits\": 120,\n  \"estimated_seconds\": 92\n}"
            }
          ]
        },
        {
          "name": "Get job status",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-API-Key",
                "value": "{{api_key}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/sdr2hdr/jobs/{{job_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "sdr2hdr",
                "jobs",
                "{{job_id}}"
              ]
            },
            "description": "Poll until status is done or failed. Failures carry the same error object as a sync response.",
            "auth": {
              "type": "noauth"
            }
          },
          "response": [
            {
              "name": "200 · done",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "X-API-Key",
                    "value": "{{api_key}}"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v1/sdr2hdr/jobs/{{job_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v1",
                    "sdr2hdr",
                    "jobs",
                    "{{job_id}}"
                  ]
                },
                "description": "Poll until status is done or failed. Failures carry the same error object as a sync response.",
                "auth": {
                  "type": "noauth"
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"job_id\": \"job_01J8ZK3M9QX4HD2N7P\",\n  \"status\": \"done\",\n  \"output\": \"s3://mls-outputs/landscape-hdr.mp4\",\n  \"billing\": {\n    \"estimated_credits\": 120,\n    \"charged_credits\": 118,\n    \"refunded\": false\n  }\n}"
            },
            {
              "name": "200 · failed (same envelope as a sync error)",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "X-API-Key",
                    "value": "{{api_key}}"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v1/sdr2hdr/jobs/{{job_id}}",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v1",
                    "sdr2hdr",
                    "jobs",
                    "{{job_id}}"
                  ]
                },
                "description": "Poll until status is done or failed. Failures carry the same error object as a sync response.",
                "auth": {
                  "type": "noauth"
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"job_id\": \"job_01J8ZK3M9QX4HD2N7P\",\n  \"status\": \"failed\",\n  \"error\": {\n    \"type\": \"processing_error\",\n    \"code\": \"processing_failed\",\n    \"message\": \"Processing failed. Retry once; if it persists, contact support with the request_id.\",\n    \"param\": null,\n    \"request_id\": \"req_01J8ZK3M9QX4HD2N7P\",\n    \"doc_url\": \"https://mlslabs.io/docs/errors.html#processing_failed\",\n    \"retryable\": false\n  },\n  \"billing\": {\n    \"estimated_credits\": 120,\n    \"charged_credits\": 0,\n    \"refunded\": true\n  }\n}"
            }
          ]
        },
        {
          "name": "Account credits",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-API-Key",
                "value": "{{api_key}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/account/credits",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "account",
                "credits"
              ]
            },
            "description": "Current credit balance and plan limits for the account.",
            "auth": {
              "type": "noauth"
            }
          },
          "response": [
            {
              "name": "200 · balance",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "X-API-Key",
                    "value": "{{api_key}}"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v1/account/credits",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v1",
                    "account",
                    "credits"
                  ]
                },
                "description": "Current credit balance and plan limits for the account.",
                "auth": {
                  "type": "noauth"
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"plan\": \"pro\",\n  \"credits_balance\": 1450,\n  \"credits_reserved\": 0,\n  \"spend_limit_usd\": 700,\n  \"spent_usd\": 128.4\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Error handling (401 / 402 / 429)",
      "item": [
        {
          "name": "401 · Invalid API key",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-API-Key",
                "value": "mls_live_revoked_or_wrong_key"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/account/credits",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "account",
                "credits"
              ]
            },
            "description": "Send a deliberately wrong key to inspect the 401 envelope.",
            "auth": {
              "type": "noauth"
            }
          },
          "response": [
            {
              "name": "401 · invalid_api_key",
              "originalRequest": {
                "method": "GET",
                "header": [
                  {
                    "key": "X-API-Key",
                    "value": "mls_live_revoked_or_wrong_key"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v1/account/credits",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v1",
                    "account",
                    "credits"
                  ]
                },
                "description": "Send a deliberately wrong key to inspect the 401 envelope.",
                "auth": {
                  "type": "noauth"
                }
              },
              "status": "Unauthorized",
              "code": 401,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                },
                {
                  "key": "X-Request-Id",
                  "value": "req_01J8ZK3M9QX4HD2N7P"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"type\": \"auth_error\",\n    \"code\": \"invalid_api_key\",\n    \"message\": \"The API key is not valid. Check the X-API-Key header or rotate the key in the dashboard.\",\n    \"param\": null,\n    \"request_id\": \"req_01J8ZK3M9QX4HD2N7P\",\n    \"doc_url\": \"https://mlslabs.io/docs/errors.html#invalid_api_key\",\n    \"retryable\": false\n  }\n}"
            }
          ]
        },
        {
          "name": "401 · Missing API key",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/account/credits",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "account",
                "credits"
              ]
            },
            "description": "No credential at all — the API answers with missing_api_key, not invalid_api_key.",
            "auth": {
              "type": "noauth"
            }
          },
          "response": [
            {
              "name": "401 · missing_api_key",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{base_url}}/v1/account/credits",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v1",
                    "account",
                    "credits"
                  ]
                },
                "description": "No credential at all — the API answers with missing_api_key, not invalid_api_key.",
                "auth": {
                  "type": "noauth"
                }
              },
              "status": "Unauthorized",
              "code": 401,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                },
                {
                  "key": "X-Request-Id",
                  "value": "req_01J8ZK3M9QX4HD2N8Q"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"type\": \"auth_error\",\n    \"code\": \"missing_api_key\",\n    \"message\": \"No API key was supplied. Send it in the X-API-Key header.\",\n    \"param\": null,\n    \"request_id\": \"req_01J8ZK3M9QX4HD2N8Q\",\n    \"doc_url\": \"https://mlslabs.io/docs/errors.html#missing_api_key\",\n    \"retryable\": false\n  }\n}"
            }
          ]
        },
        {
          "name": "402 · Insufficient credits",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-API-Key",
                "value": "{{api_key}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/sdr2hdr/jobs",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "sdr2hdr",
                "jobs"
              ]
            },
            "description": "Valid key, empty balance. details carries the exact shortfall for the top-up prompt.",
            "auth": {
              "type": "noauth"
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"input\": \"s3://mls-samples/landscape-sdr.mp4\",\n  \"output\": \"s3://mls-outputs/landscape-hdr.mp4\",\n  \"target\": \"hdr10\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "402 · insufficient_credits",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "X-API-Key",
                    "value": "{{api_key}}"
                  },
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v1/sdr2hdr/jobs",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v1",
                    "sdr2hdr",
                    "jobs"
                  ]
                },
                "description": "Valid key, empty balance. details carries the exact shortfall for the top-up prompt.",
                "auth": {
                  "type": "noauth"
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"input\": \"s3://mls-samples/landscape-sdr.mp4\",\n  \"output\": \"s3://mls-outputs/landscape-hdr.mp4\",\n  \"target\": \"hdr10\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Payment Required",
              "code": 402,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                },
                {
                  "key": "X-Request-Id",
                  "value": "req_01J8ZK3M9QX4HD2N9R"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"type\": \"billing_error\",\n    \"code\": \"insufficient_credits\",\n    \"message\": \"Not enough credits for this job. Required 120, available 45.\",\n    \"param\": null,\n    \"request_id\": \"req_01J8ZK3M9QX4HD2N9R\",\n    \"doc_url\": \"https://mlslabs.io/docs/errors.html#insufficient_credits\",\n    \"retryable\": false,\n    \"details\": {\n      \"required_credits\": 120,\n      \"available_credits\": 45\n    }\n  }\n}"
            }
          ]
        },
        {
          "name": "402 · Spend limit exceeded",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-API-Key",
                "value": "{{api_key}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/sdr2hdr/jobs",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "sdr2hdr",
                "jobs"
              ]
            },
            "description": "Balance is fine, but the monthly spend cap blocks the job.",
            "auth": {
              "type": "noauth"
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"input\": \"s3://mls-samples/landscape-sdr.mp4\",\n  \"output\": \"s3://mls-outputs/landscape-hdr.mp4\",\n  \"target\": \"hdr10\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "402 · spend_limit_exceeded",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "X-API-Key",
                    "value": "{{api_key}}"
                  },
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v1/sdr2hdr/jobs",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v1",
                    "sdr2hdr",
                    "jobs"
                  ]
                },
                "description": "Balance is fine, but the monthly spend cap blocks the job.",
                "auth": {
                  "type": "noauth"
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"input\": \"s3://mls-samples/landscape-sdr.mp4\",\n  \"output\": \"s3://mls-outputs/landscape-hdr.mp4\",\n  \"target\": \"hdr10\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Payment Required",
              "code": 402,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                },
                {
                  "key": "X-Request-Id",
                  "value": "req_01J8ZK3M9QX4HD2NAR"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"type\": \"billing_error\",\n    \"code\": \"spend_limit_exceeded\",\n    \"message\": \"Monthly spend limit reached. This job would exceed the cap on your account.\",\n    \"param\": null,\n    \"request_id\": \"req_01J8ZK3M9QX4HD2NAR\",\n    \"doc_url\": \"https://mlslabs.io/docs/errors.html#spend_limit_exceeded\",\n    \"retryable\": false,\n    \"details\": {\n      \"spend_limit_usd\": 700,\n      \"spent_usd\": 700,\n      \"reset_at\": \"2026-10-01T00:00:00Z\"\n    }\n  }\n}"
            }
          ]
        },
        {
          "name": "429 · Rate limit exceeded",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-API-Key",
                "value": "{{api_key}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/sdr2hdr/jobs",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "sdr2hdr",
                "jobs"
              ]
            },
            "description": "Fire this in a loop to see throttling. Honour Retry-After before resending.",
            "auth": {
              "type": "noauth"
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"input\": \"s3://mls-samples/landscape-sdr.mp4\",\n  \"output\": \"s3://mls-outputs/landscape-hdr.mp4\",\n  \"target\": \"hdr10\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "429 · rate_limit_exceeded",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "X-API-Key",
                    "value": "{{api_key}}"
                  },
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v1/sdr2hdr/jobs",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v1",
                    "sdr2hdr",
                    "jobs"
                  ]
                },
                "description": "Fire this in a loop to see throttling. Honour Retry-After before resending.",
                "auth": {
                  "type": "noauth"
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"input\": \"s3://mls-samples/landscape-sdr.mp4\",\n  \"output\": \"s3://mls-outputs/landscape-hdr.mp4\",\n  \"target\": \"hdr10\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Too Many Requests",
              "code": 429,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                },
                {
                  "key": "X-Request-Id",
                  "value": "req_01J8ZK3M9QX4HD2NBR"
                },
                {
                  "key": "Retry-After",
                  "value": "2"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"type\": \"rate_limit_error\",\n    \"code\": \"rate_limit_exceeded\",\n    \"message\": \"Rate limit exceeded. This plan allows 20 requests per second.\",\n    \"param\": null,\n    \"request_id\": \"req_01J8ZK3M9QX4HD2NBR\",\n    \"doc_url\": \"https://mlslabs.io/docs/errors.html#rate_limit_exceeded\",\n    \"retryable\": true,\n    \"details\": {\n      \"limit\": 20,\n      \"window_seconds\": 1,\n      \"retry_after_seconds\": 2\n    }\n  }\n}"
            }
          ]
        },
        {
          "name": "429 · Concurrency limit exceeded",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-API-Key",
                "value": "{{api_key}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/sdr2hdr/jobs",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "sdr2hdr",
                "jobs"
              ]
            },
            "description": "Same status as throttling, different fix: wait for a running job to finish.",
            "auth": {
              "type": "noauth"
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"input\": \"s3://mls-samples/landscape-sdr.mp4\",\n  \"output\": \"s3://mls-outputs/landscape-hdr.mp4\",\n  \"target\": \"hdr10\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "429 · concurrency_limit_exceeded",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "X-API-Key",
                    "value": "{{api_key}}"
                  },
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": {
                  "raw": "{{base_url}}/v1/sdr2hdr/jobs",
                  "host": [
                    "{{base_url}}"
                  ],
                  "path": [
                    "v1",
                    "sdr2hdr",
                    "jobs"
                  ]
                },
                "description": "Same status as throttling, different fix: wait for a running job to finish.",
                "auth": {
                  "type": "noauth"
                },
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"input\": \"s3://mls-samples/landscape-sdr.mp4\",\n  \"output\": \"s3://mls-outputs/landscape-hdr.mp4\",\n  \"target\": \"hdr10\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "Too Many Requests",
              "code": 429,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                },
                {
                  "key": "X-Request-Id",
                  "value": "req_01J8ZK3M9QX4HD2NCR"
                },
                {
                  "key": "Retry-After",
                  "value": "5"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"type\": \"rate_limit_error\",\n    \"code\": \"concurrency_limit_exceeded\",\n    \"message\": \"Too many jobs running at once. This plan allows 8 concurrent jobs.\",\n    \"param\": null,\n    \"request_id\": \"req_01J8ZK3M9QX4HD2NCR\",\n    \"doc_url\": \"https://mlslabs.io/docs/errors.html#concurrency_limit_exceeded\",\n    \"retryable\": true,\n    \"details\": {\n      \"concurrency_limit\": 8,\n      \"running_jobs\": 8\n    }\n  }\n}"
            }
          ]
        }
      ]
    }
  ]
}
