Work with this as data
Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/magichour-image-projects-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
OpenAPI Specification
openapi: 3.2.0
info:
title: Magic Hour Image Projects API
version: beta
description: "\nMagic Hour provides an API (beta) that can be integrated into your own application to generate videos and images using AI. \n\nWebhook documentation can be found [here](https://docs.magichour.ai/webhook-reference).\n\nIf you have any questions, please reach out to us via [discord](https://discord.gg/JX5rgsZaJp).\n\n# Authentication\n\nEvery request requires an API key.\n\nTo get started, first generate your API key [here](https://magichour.ai/developer?tab=api-keys&utm_source=docs&utm_medium=referral&utm_campaign=api-reference).\n\nThen, add the `Authorization` header to the request.\n\n| Key | Value |\n|-|-|\n| Authorization | Bearer mhk_live_apikey |\n\n> **Warning**: any API call that renders a video will utilize credits in your account.\n"
termsOfService: https://magichour.ai/terms-of-service
servers:
- url: https://api.magichour.ai
tags:
- name: Image Projects
description: API related to image projects
paths:
/v1/image-projects/{id}:
get:
description: "Check the progress of a image project. The `downloads` field is populated after a successful render.\n \n**Statuses**\n- `queued` — waiting to start\n- `rendering` — in progress\n- `complete` — ready; see `downloads`\n- `error` — a failure occurred (see `error`)\n- `canceled` — user canceled\n- `draft` — not used"
summary: Get image details
tags:
- Image Projects
parameters:
- name: id
in: path
required: true
schema:
type: string
example: cuid-example
description: Unique ID of the image project. This value is returned by all of the POST APIs that create an image.
operationId: imageProjects.getDetails
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
id:
type: string
example: cuid-example
description: Unique ID of the image. Use it with the [Get image Project API](https://docs.magichour.ai/api-reference/image-projects/get-image-details) to fetch status and downloads.
name:
type:
- string
- 'null'
description: The name of the image.
example: Example Name
status:
type: string
enum:
- draft
- queued
- rendering
- complete
- error
- canceled
description: 'The status of the image.
- `draft` - the project was created but has not been submitted for rendering
- `queued` - the job is waiting for an available server
- `rendering` - the job is being processed; the `image.started` webhook event fires when rendering begins
- `complete` - the job finished successfully; fires `image.completed`
- `error` - the job failed during processing; fires `image.errored`
- `canceled` - the job was manually canceled (for example from the Magic Hour web app)
**Note:** `rendering`, `complete`, and `error` have matching webhook events; `canceled` does not - a canceled job emits no webhook event, so poll this endpoint to detect cancellation.'
example: complete
image_count:
type: integer
description: Number of images generated
example: 1
type:
type: string
description: The type of the image project. Possible values are FACE_EDITOR, AI_IMAGE_EDITOR, AI_SELFIE, AI_HEADSHOT, AI_INFLUENCER, AI_IMAGE, AI_MEME, CLOTHES_CHANGER, BACKGROUND_REMOVER, FACE_SWAP, IMAGE_UPSCALER, IMAGE_ENHANCER, AI_GIF, QR_CODE, PHOTO_EDITOR, PHOTO_COLORIZER, HEAD_SWAP, BODY_SWAP, STORYBOARD, IMAGE_EXPANDER
example: AI_IMAGE
created_at:
type: string
format: date-time
enabled:
type: boolean
description: Whether this resource is active. If false, it is deleted.
credits_charged:
type: integer
example: 5
description: "The amount of credits deducted from your account to generate the image. We charge credits right when the request is made. \n\nIf an error occurred while generating the image(s), credits will be refunded and this field will be updated to include the refund."
downloads:
type: array
items:
type: object
properties:
url:
type: string
format: uri
example: https://videos.magichour.ai/id/output.png
expires_at:
type: string
format: date-time
example: '2024-10-19T05:16:19.027Z'
required:
- url
- expires_at
description: The download url and expiration date of the image project
error:
type:
- object
- 'null'
properties:
message:
type: string
description: Details on the reason why a failure happened.
example: Please use an image with a detectable face
code:
type: string
example: no_source_face
description: An error code to indicate why a failure happened.
required:
- message
- code
description: In the case of an error, this object will contain the error encountered during video render
example: null
required:
- id
- name
- status
- image_count
- type
- created_at
- enabled
- credits_charged
- downloads
- error
description: Success
'400':
description: Invalid Request
content:
application/json:
schema:
type: object
properties:
message:
type: string
required:
- message
description: The request is invalid
example:
message: Missing request body
'401':
description: Unauthorized
content:
application/json:
schema:
type: object
properties:
message:
type: string
enum:
- Unauthorized
required:
- message
description: The request is not properly authenticated
example:
message: Unauthorized
'402':
description: Payment Required
content:
application/json:
schema:
type: object
properties:
message:
type: string
required:
- message
description: The request requires payment
example:
message: Payment required
'404':
description: Not Found
content:
application/json:
schema:
type: object
properties:
message:
type: string
enum:
- Not Found
required:
- message
description: Requested resource is not found
example:
message: Not Found
security:
- bearerAuth: []
x-codeSamples:
- lang: python
source: 'from magic_hour import Client
from os import getenv
client = Client(token=getenv("API_TOKEN"))
res = client.v1.image_projects.get(id="cuid-example")'
- lang: javascript
source: 'import { Client } from "magic-hour";
const client = new Client({ token: process.env["API_TOKEN"]!! });
const res = await client.v1.imageProjects.get({ id: "cuid-example" });'
- lang: go
source: "package main\n\nimport (\n\tos \"os\"\n\n\tsdk \"github.com/magichourhq/magic-hour-go/client\"\n\timage_projects \"github.com/magichourhq/magic-hour-go/resources/v1/image_projects\"\n)\n\nfunc main() {\n\tclient := sdk.NewClient(\n\t\tsdk.WithBearerAuth(os.Getenv(\"API_TOKEN\")),\n\t)\n\tres, err := client.V1.ImageProjects.Get(image_projects.GetRequest{\n\t\tId: \"cuid-example\",\n\t})\n}"
- lang: rust
source: "let client = magic_hour::Client::default()\n .with_bearer_auth(&std::env::var(\"API_TOKEN\").unwrap());\nlet res = client\n .v1()\n .image_projects()\n .get(magic_hour::resources::v1::image_projects::GetRequest {\n id: \"cuid-example\".to_string(),\n })\n .await;"
- lang: curl
source: "curl --request GET \\\n --url https://api.magichour.ai/v1/image-projects/id \\\n --header 'accept: application/json' \\\n --header 'authorization: Bearer <token>'"
- lang: php
source: "<?php\n\n$curl = curl_init();\n\ncurl_setopt_array($curl, [\n CURLOPT_URL => \"https://api.magichour.ai/v1/image-projects/id\",\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_ENCODING => \"\",\n CURLOPT_MAXREDIRS => 10,\n CURLOPT_TIMEOUT => 30,\n CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n CURLOPT_CUSTOMREQUEST => \"GET\",\n CURLOPT_HTTPHEADER => [\n \"accept: application/json\",\n \"authorization: Bearer <token>\"\n ],\n]);\n\n$response = curl_exec($curl);\n$err = curl_error($curl);\n\ncurl_close($curl);\n\nif ($err) {\n echo \"cURL Error #:\" . $err;\n} else {\n echo $response;\n}"
- lang: java
source: "HttpResponse<String> response = Unirest.get(\"https://api.magichour.ai/v1/image-projects/id\")\n .header(\"accept\", \"application/json\")\n .header(\"authorization\", \"Bearer <token>\")\n .asString();"
delete:
description: Permanently delete the rendered image(s). This action is not reversible, please be sure before deleting.
summary: Delete image
tags:
- Image Projects
parameters:
- name: id
in: path
required: true
schema:
type: string
example: cuid-example
description: Unique ID of the image project. This value is returned by all of the POST APIs that create an image.
operationId: imageProjects.delete
responses:
'204':
description: '204'
'400':
description: Invalid Request
content:
application/json:
schema:
type: object
properties:
message:
type: string
required:
- message
description: The request is invalid
example:
message: Missing request body
'401':
description: Unauthorized
content:
application/json:
schema:
type: object
properties:
message:
type: string
enum:
- Unauthorized
required:
- message
description: The request is not properly authenticated
example:
message: Unauthorized
'402':
description: Payment Required
content:
application/json:
schema:
type: object
properties:
message:
type: string
required:
- message
description: The request requires payment
example:
message: Payment required
'404':
description: Not Found
content:
application/json:
schema:
type: object
properties:
message:
type: string
enum:
- Not Found
required:
- message
description: Requested resource is not found
example:
message: Not Found
security:
- bearerAuth: []
x-codeSamples:
- lang: python
source: 'from magic_hour import Client
from os import getenv
client = Client(token=getenv("API_TOKEN"))
res = client.v1.image_projects.delete(id="cuid-example")'
- lang: javascript
source: 'import { Client } from "magic-hour";
const client = new Client({ token: process.env["API_TOKEN"]!! });
const res = await client.v1.imageProjects.delete({ id: "cuid-example" });'
- lang: go
source: "package main\n\nimport (\n\tos \"os\"\n\n\tsdk \"github.com/magichourhq/magic-hour-go/client\"\n\timage_projects \"github.com/magichourhq/magic-hour-go/resources/v1/image_projects\"\n)\n\nfunc main() {\n\tclient := sdk.NewClient(\n\t\tsdk.WithBearerAuth(os.Getenv(\"API_TOKEN\")),\n\t)\n\terr := client.V1.ImageProjects.Delete(image_projects.DeleteRequest{\n\t\tId: \"cuid-example\",\n\t})\n}"
- lang: rust
source: "let client = magic_hour::Client::default()\n .with_bearer_auth(&std::env::var(\"API_TOKEN\").unwrap());\nlet res = client\n .v1()\n .image_projects()\n .delete(magic_hour::resources::v1::image_projects::DeleteRequest {\n id: \"cuid-example\".to_string(),\n })\n .await;"
- lang: curl
source: "curl --request DELETE \\\n --url https://api.magichour.ai/v1/image-projects/id \\\n --header 'accept: application/json' \\\n --header 'authorization: Bearer <token>'"
- lang: php
source: "<?php\n\n$curl = curl_init();\n\ncurl_setopt_array($curl, [\n CURLOPT_URL => \"https://api.magichour.ai/v1/image-projects/id\",\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_ENCODING => \"\",\n CURLOPT_MAXREDIRS => 10,\n CURLOPT_TIMEOUT => 30,\n CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n CURLOPT_CUSTOMREQUEST => \"DELETE\",\n CURLOPT_HTTPHEADER => [\n \"accept: application/json\",\n \"authorization: Bearer <token>\"\n ],\n]);\n\n$response = curl_exec($curl);\n$err = curl_error($curl);\n\ncurl_close($curl);\n\nif ($err) {\n echo \"cURL Error #:\" . $err;\n} else {\n echo $response;\n}"
- lang: java
source: "HttpResponse<String> response = Unirest.delete(\"https://api.magichour.ai/v1/image-projects/id\")\n .header(\"accept\", \"application/json\")\n .header(\"authorization\", \"Bearer <token>\")\n .asString();"
/v1/ai-clothes-changer:
post:
description: Change outfits in photos in seconds with just a photo reference. Each photo costs 25 credits.
summary: AI Clothes Changer
tags:
- Image Projects
parameters: []
operationId: aiClothesChanger.createImage
requestBody:
required: true
description: Body
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: Give your image a custom name for easy identification.
example: My Clothes Changer image
default: Clothes Changer - dateTime
assets:
type: object
properties:
person_file_path:
type: string
minLength: 1
description: 'The image with the person. This value is either
- a direct URL to the video file
- `file_path` field from the response of the [upload urls API](https://docs.magichour.ai/api-reference/files/generate-asset-upload-urls).
See the [file upload guide](https://docs.magichour.ai/api-reference/files/generate-asset-upload-urls#input-file) for details.
'
example: api-assets/id/model.png
garment_file_path:
type: string
minLength: 1
description: 'The image of the outfit. This value is either
- a direct URL to the video file
- `file_path` field from the response of the [upload urls API](https://docs.magichour.ai/api-reference/files/generate-asset-upload-urls).
See the [file upload guide](https://docs.magichour.ai/api-reference/files/generate-asset-upload-urls#input-file) for details.
'
example: api-assets/id/outfit.png
garment_type:
type: string
enum:
- entire_outfit
- upper_body
- lower_body
- dresses
description: "Type of garment to swap. If not provided, swaps the entire outfit. \n* `upper_body` - for shirts/jackets \n* `lower_body` - for pants/skirts \n* `dresses` - for entire outfit (deprecated, use `entire_outfit` instead) \n* `entire_outfit` - for entire outfit"
example: entire_outfit
required:
- person_file_path
- garment_file_path
description: Provide the assets for clothes changer
required:
- assets
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
id:
type: string
example: cuid-example
description: Unique ID of the image. Use it with the [Get image Project API](https://docs.magichour.ai/api-reference/image-projects/get-image-details) to fetch status and downloads.
credits_charged:
type: integer
description: "The amount of credits deducted from your account to generate the image. We charge credits right when the request is made. \n\nIf an error occurred while generating the image(s), credits will be refunded and this field will be updated to include the refund."
example: 25
required:
- id
- credits_charged
description: Success
'400':
description: Invalid Request
content:
application/json:
schema:
type: object
properties:
message:
type: string
required:
- message
description: The request is invalid
example:
message: Missing request body
'401':
description: Unauthorized
content:
application/json:
schema:
type: object
properties:
message:
type: string
enum:
- Unauthorized
required:
- message
description: The request is not properly authenticated
example:
message: Unauthorized
'402':
description: Payment Required
content:
application/json:
schema:
type: object
properties:
message:
type: string
required:
- message
description: The request requires payment
example:
message: Payment required
'404':
description: Not Found
content:
application/json:
schema:
type: object
properties:
message:
type: string
enum:
- Not Found
required:
- message
description: Requested resource is not found
example:
message: Not Found
'422':
description: Unprocessable Entity
content:
application/json:
schema:
type: object
properties:
message:
type: string
example: Unable to create image
required:
- message
description: Unprocessable Entity
security:
- bearerAuth: []
x-codeSamples:
- lang: python
source: "from magic_hour import Client\nfrom os import getenv\n\nclient = Client(token=getenv(\"API_TOKEN\"))\nres = client.v1.ai_clothes_changer.generate(\n assets={\n \"garment_file_path\": \"/path/to/outfit.png\",\n \"garment_type\": \"upper_body\",\n \"person_file_path\": \"/path/to/model.png\",\n },\n name=\"Clothes Changer image\",\n wait_for_completion=True,\n download_outputs=True,\n download_directory=\".\",\n)"
- lang: javascript
source: "import { Client } from \"magic-hour\";\n\nconst client = new Client({ token: process.env[\"API_TOKEN\"]!! });\nconst res = await client.v1.aiClothesChanger.generate(\n {\n assets: {\n garmentFilePath: \"/path/to/outfit.png\",\n garmentType: \"upper_body\",\n personFilePath: \"/path/to/model.png\",\n },\n name: \"Clothes Changer image\",\n },\n {\n waitForCompletion: true,\n downloadOutputs: true,\n downloadDirectory: \".\",\n },\n);"
- lang: go
source: "package main\n\nimport (\n\tos \"os\"\n\n\tsdk \"github.com/magichourhq/magic-hour-go/client\"\n\tnullable \"github.com/magichourhq/magic-hour-go/nullable\"\n\tai_clothes_changer \"github.com/magichourhq/magic-hour-go/resources/v1/ai_clothes_changer\"\n\ttypes \"github.com/magichourhq/magic-hour-go/types\"\n)\n\nfunc main() {\n\tclient := sdk.NewClient(\n\t\tsdk.WithBearerAuth(os.Getenv(\"API_TOKEN\")),\n\t)\n\tres, err := client.V1.AiClothesChanger.Create(ai_clothes_changer.CreateRequest{\n\t\tAssets: types.V1AiClothesChangerCreateBodyAssets{\n\t\t\tGarmentFilePath: \"api-assets/id/outfit.png\",\n\t\t\tGarmentType: nullable.NewValue(types.V1AiClothesChangerCreateBodyAssetsGarmentTypeEnumEntireOutfit),\n\t\t\tPersonFilePath: \"api-assets/id/model.png\",\n\t\t},\n\t\tName: nullable.NewValue(\"My Clothes Changer image\"),\n\t})\n}"
- lang: rust
source: "let client = magic_hour::Client::default()\n .with_bearer_auth(&std::env::var(\"API_TOKEN\").unwrap());\nlet res = client\n .v1()\n .ai_clothes_changer()\n .create(magic_hour::resources::v1::ai_clothes_changer::CreateRequest {\n assets: magic_hour::models::V1AiClothesChangerCreateBodyAssets {\n garment_file_path: \"api-assets/id/outfit.png\".to_string(),\n garment_type: Some(\n magic_hour::models::V1AiClothesChangerCreateBodyAssetsGarmentTypeEnum::EntireOutfit,\n ),\n person_file_path: \"api-assets/id/model.png\".to_string(),\n },\n name: Some(\"My Clothes Changer image\".to_string()),\n })\n .await;"
- lang: curl
source: "curl --request POST \\\n --url https://api.magichour.ai/v1/ai-clothes-changer \\\n --header 'accept: application/json' \\\n --header 'authorization: Bearer <token>' \\\n --header 'content-type: application/json' \\\n --data '\n{\n \"name\": \"My Clothes Changer image\",\n \"assets\": {\n \"person_file_path\": \"api-assets/id/model.png\",\n \"garment_file_path\": \"api-assets/id/outfit.png\",\n \"garment_type\": \"entire_outfit\"\n }\n}\n'"
- lang: php
source: "<?php\n\n$curl = curl_init();\n\ncurl_setopt_array($curl, [\n CURLOPT_URL => \"https://api.magichour.ai/v1/ai-clothes-changer\",\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_ENCODING => \"\",\n CURLOPT_MAXREDIRS => 10,\n CURLOPT_TIMEOUT => 30,\n CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n CURLOPT_CUSTOMREQUEST => \"POST\",\n CURLOPT_POSTFIELDS => json_encode([\n 'name' => 'My Clothes Changer image',\n 'assets' => [\n 'person_file_path' => 'api-assets/id/model.png',\n 'garment_file_path' => 'api-assets/id/outfit.png',\n 'garment_type' => 'entire_outfit'\n ]\n ]),\n CURLOPT_HTTPHEADER => [\n \"accept: application/json\",\n \"authorization: Bearer <token>\",\n \"content-type: application/json\"\n ],\n]);\n\n$response = curl_exec($curl);\n$err = curl_error($curl);\n\ncurl_close($curl);\n\nif ($err) {\n echo \"cURL Error #:\" . $err;\n} else {\n echo $response;\n}"
- lang: java
source: "HttpResponse<String> response = Unirest.post(\"https://api.magichour.ai/v1/ai-clothes-changer\")\n .header(\"accept\", \"application/json\")\n .header(\"content-type\", \"application/json\")\n .header(\"authorization\", \"Bearer <token>\")\n .body(\"{\\\"name\\\":\\\"My Clothes Changer image\\\",\\\"assets\\\":{\\\"person_file_path\\\":\\\"api-assets/id/model.png\\\",\\\"garment_file_path\\\":\\\"api-assets/id/outfit.png\\\",\\\"garment_type\\\":\\\"entire_outfit\\\"}}\")\n .asString();"
/v1/ai-face-editor:
post:
description: Edit facial features of an image using AI. Each edit costs 1 frame. The height/width of the output image depends on your subscription. Please refer to our [pricing](https://magichour.ai/pricing) page for more details
summary: AI Face Editor
tags:
- Image Projects
parameters: []
operationId: aiFaceEditor.editImage
requestBody:
required: true
description: Body
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: Give your image a custom name for easy identification.
example: My Face Editor image
default: Face Editor - dateTime
assets:
type: object
properties:
image_file_path:
type: string
minLength: 1
description: 'This is the image whose face will be edited. This value is either
- a direct URL to the video file
- `file_path` field from the response of the [upload urls API](https://docs.magichour.ai/api-reference/files/generate-asset-upload-urls).
See the [file upload guide](https://docs.magichour.ai/api-reference/files/generate-asset-upload-urls#input-file) for details.
'
example: api-assets/id/1234.png
required:
- image_file_path
description: Provide the assets for face editor
style:
type: object
properties:
enhance_face:
default: false
type: boolean
description: Enhance face features
example: false
eyebrow_direction:
default: 0
type: number
minimum: -100
maximum: 100
multipleOf: 5
description: Eyebrow direction (-100 to 100), in increments of 5
example: 0
eye_gaze_horizontal:
default: 0
type: number
minimum: -100
maximum: 100
multipleOf: 5
description: Horizontal eye gaze (-100 to 100), in increments of 5
example: 0
eye_gaze_vertical:
default: 0
type: number
minimum: -100
maximum: 100
multipleOf: 5
description: Vertical eye gaze (-100 to 100), in increments of 5
example: 0
eye_open_ratio:
default: 0
type: number
minimum: -100
maximum: 100
multipleOf: 5
description: Eye open ratio (-100 to 100), in increments of 5
example: 0
lip_open_ratio:
default: 0
type: number
minimum: -100
maximum: 100
multipleOf: 5
description: Lip open ratio (-100 to 100), in increments of 5
example: 0
head_roll:
default: 0
type: number
minimum: -100
maximum: 100
multipleOf: 5
description: Head roll (-100 to 100), in increments of 5
example: 0
mouth_grim:
default: 0
type: number
minimum: -100
maximum: 100
multipleOf: 5
description: Mouth grim (-100 to 100), in increments of 5
example: 0
mouth_pout:
default: 0
type: number
minimum: -100
maximum: 100
multipleOf: 5
description: Mouth pout (-100 to 100), in increments of 5
example: 0
mouth_purse:
default: 0
type: number
minimum: -100
maximum: 100
multipleOf: 5
description: Mouth purse (-100 to 100), in increments of 5
example: 0
mouth_smile:
default: 0
type: number
minimum: -100
maximum: 100
multipleOf: 5
description: Mouth smile (-100 to 100), in increments of 5
example: 0
mouth_position_horizontal:
default: 0
type: number
minimum: -100
maximum: 100
multipleOf: 5
description: Horizontal mouth position (-100 to 100), in increments of 5
example: 0
mouth_position_vertical:
default: 0
type: number
minimum: -100
maximum: 100
multipleOf: 5
description: Vertical mouth position (-100 to 100), in increments of 5
example: 0
head_pitch:
default: 0
type: number
minimum: -100
maximum: 100
multipleOf: 5
description: Head pitch (-100 to 100), in increments of 5
example: 0
# --- truncated at 32 KB (171 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/magichour/refs/heads/main/openapi/magichour-image-projects-api-openapi.yml