{ "kind": "open-flow-workflow", "version": 1, "name": "Generate Telegram Images with Magic Hour", "content": { "modelVersion": 14, "document": { "bindings": {}, "graph": { "nodes": { "n_ab9d29500cfd3df8": { "name": "Receive a Telegram message", "kind": "integration", "config": { "updates": { "kind": "value", "value": [ "message" ] }, "chatIds": { "kind": "value", "value": [] }, "userIds": { "kind": "value", "value": [] }, "dropPendingUpdates": { "kind": "value", "value": false } }, "definition": { "configInputs": [ { "description": "Only accept updates from these numeric Telegram chat IDs. Empty means every chat.", "jsonSchema": { "type": "array", "items": { "type": "string", "pattern": "^-?[0-9]{1,20}$" }, "maxItems": 100, "uniqueItems": true }, "nullable": false, "handle": "chatIds", "value": [] }, { "description": "Discard updates queued before the webhook is created or resumed.", "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "dropPendingUpdates", "value": true }, { "description": "Telegram update types that trigger a Run. Use * for the Telegram default set.", "jsonSchema": { "type": "array", "items": { "enum": [ "*", "message", "edited_message", "channel_post", "edited_channel_post", "business_connection", "business_message", "edited_business_message", "deleted_business_messages", "guest_message", "message_reaction", "message_reaction_count", "inline_query", "chosen_inline_result", "callback_query", "shipping_query", "pre_checkout_query", "purchased_paid_media", "poll", "poll_answer", "my_chat_member", "chat_member", "chat_join_request", "chat_boost", "removed_chat_boost", "managed_bot", "subscription" ] }, "minItems": 1, "uniqueItems": true }, "nullable": false, "handle": "updates" }, { "description": "Only accept updates from these numeric Telegram user IDs. Empty means every user.", "jsonSchema": { "type": "array", "items": { "type": "string", "pattern": "^[0-9]{1,20}$" }, "maxItems": 100, "uniqueItems": true }, "nullable": false, "handle": "userIds", "value": [] } ], "definitionVersion": 2, "description": "Triggers when the connected Telegram bot receives a selected update.", "displayName": "Bot Update", "key": "telegram.on_update", "name": "on_update", "outputs": [ { "jsonSchema": { "type": "object" }, "nullable": false, "handle": "body" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "deliveryId" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "event" } ], "provider": "telegram", "type": "integration", "endpoint": { "body": { "allowArray": false, "allowEmpty": false, "formats": [ "json" ] }, "methods": [ "POST" ], "successStatus": 200 } } }, "n_cb6f0970d983220d": { "inputs": { "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_ab9d29500cfd3df8", "output": "body" } ] } }, "name": "Prepare the image prompt", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "object" }, "nullable": false, "handle": "body" } ], "outputs": [ { "jsonSchema": { "anyOf": [ { "type": "integer", "description": "A union variant." }, { "type": "string", "pattern": "^-?\\d+$", "description": "A numeric Telegram chat identifier encoded as a string." }, { "type": "string", "pattern": "^@[A-Za-z0-9_]+$", "description": "A Telegram @username that identifies a public chat or channel." } ], "description": "The target Telegram chat ID or channel username." }, "nullable": false, "handle": "chatId" }, { "jsonSchema": { "type": "object", "properties": { "prompt": { "type": "string", "minLength": 1, "description": "The prompt used for the image(s)." }, "tool": { "type": "string", "enum": [ "ai-anime-generator", "ai-art-generator", "ai-background-generator", "ai-character-generator", "ai-face-generator", "ai-fashion-generator", "ai-icon-generator", "ai-illustration-generator", "ai-interior-design-generator", "ai-landscape-generator", "ai-logo-generator", "ai-manga-generator", "ai-outfit-generator", "ai-pattern-generator", "ai-photo-generator", "ai-sketch-generator", "ai-tattoo-generator", "album-cover-generator", "animated-characters-generator", "architecture-generator", "book-cover-generator", "comic-book-generator", "dark-fantasy-ai", "disney-ai-generator", "dnd-ai-art-generator", "emoji-generator", "fantasy-map-generator", "graffiti-generator", "movie-poster-generator", "optical-illusion-generator", "pokemon-generator", "south-park-character-generator", "superhero-generator", "thumbnail-maker", "general" ], "description": "The art style to use for image generation. Defaults to 'general' if not provided." } }, "required": [ "prompt" ], "additionalProperties": true, "description": "The art style to use for image generation." }, "nullable": false, "handle": "style" } ], "name": "Prepare the image prompt", "moduleId": "n_f56ea5c3852b6baa", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_792b5a2dcb058dc8": { "inputs": { "model": { "kind": "value", "value": "flux-2-klein" }, "image_count": { "kind": "value", "value": 1 }, "resolution": { "kind": "value", "value": "640px" }, "aspect_ratio": { "kind": "value", "value": "1:1" }, "style": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_cb6f0970d983220d", "output": "style" } ] } }, "name": "Generate the image", "kind": "task", "task": { "inputs": [ { "description": "Give your image a custom name for easy identification.", "jsonSchema": { "type": "string", "description": "Give your image a custom name for easy identification." }, "nullable": true, "handle": "name", "value": null }, { "description": "Number of images to generate. Maximum varies by model.", "jsonSchema": { "type": "integer", "minimum": 1, "maximum": 16, "description": "Number of images to generate. Maximum varies by model." }, "nullable": false, "handle": "image_count" }, { "description": "The AI model to use for image generation. Each model has different capabilities and costs.\n\n**Models:**\n- `default` - Use the model we recommend, which will change over time. This is recommended unless you need a specific model. This is the default behavior.\n- `flux-2-klein` - from 5 credits/image\n - Supported resolutions: 640px, 1k, 2k\n - Available for tiers: free, creator, pro, business\n - Image count allowed: 1\n- `flux-schnell` - from 5 credits/image\n - Supported resolutions: 640px, 1k, 2k\n - Available for tiers: free, creator, pro, business\n - Image count allowed: 1, 2, 3, 4\n- `gpt-image-2` - from 50 credits/image\n - Supported resolutions: 640px, 1k, 2k, 4k\n - Available for tiers: creator, pro, business\n - Image count allowed: 1, 2, 3, 4\n- `gpt-image-2.5-flare` - from 100 credits/image\n - Supported resolutions: 640px, 1k, 2k, 4k\n - Available for tiers: creator, pro, business\n - Image count allowed: 1, 2, 3, 4\n- `krea-2` - from 10 credits/image\n - Supported resolutions: 640px, 1k\n - Available for tiers: free, creator, pro, business\n - Image count allowed: 1\n- `nano-banana` - from 50 credits/image\n - Supported resolutions: 640px, 1k\n - Available for tiers: creator, pro, business\n - Image count allowed: 1, 2, 3, 4\n- `nano-banana-2` - from 100 credits/image\n - Supported resolutions: 640px, 1k, 2k, 4k\n - Available for tiers: creator, pro, business\n - Image count allowed: 1, 4, 9, 16\n- `nano-banana-2-lite` - from 50 credits/image\n - Supported resolutions: 640px, 1k\n - Available for tiers: creator, pro, business\n - Image count allowed: 1, 2, 3, 4\n- `nano-banana-2.1` - from 50 credits/image\n - Supported resolutions: 640px, 1k, 2k, 4k\n - Available for tiers: creator, pro, business\n - Image count allowed: 1, 4, 9, 16\n- `nano-banana-pro` - from 150 credits/image\n - Supported resolutions: 1k, 2k, 4k\n - Available for tiers: creator, pro, business\n - Image count allowed: 1, 4, 9, 16\n- `qwen-image-2.1` - from 10 credits/image\n - Supported resolutions: 640px, 1k, 2k\n - Available for tiers: free, creator, pro, business\n - Image count allowed: 1, 2, 3, 4\n- `seedream-v4` - from 40 credits/image\n - Supported resolutions: 640px, 1k, 2k, 4k\n - Available for tiers: creator, pro, business\n - Image count allowed: 1, 2, 3, 4\n- `seedream-v5-pro` - from 75 credits/image\n - Supported resolutions: 640px, 1k, 2k\n - Available for tiers: creator, pro, business\n - Image count allowed: 1, 2, 3, 4\n- `z-image-turbo` - from 5 credits/image\n - Supported resolutions: 640px, 1k, 2k\n - Available for tiers: free, creator, pro, business\n - Image count allowed: 1, 2, 3, 4\n\n**Deprecated Enum Values:**\n- `seedream` - Use `seedream-v4` instead.\n", "jsonSchema": { "type": "string", "enum": [ "default", "z-image-turbo", "gpt-image-2", "qwen-image-2.1", "flux-2-klein", "nano-banana-2", "nano-banana-2.1", "nano-banana-pro", "krea-2", "seedream-v5-pro", "nano-banana-2-lite", "gpt-image-2.5-flare", "seedream-v4", "nano-banana", "flux-schnell", "seedream" ], "description": "The AI model to use for image generation. Each model has different capabilities and costs.\n\n**Models:**\n- `default` - Use the model we recommend, which will change over time. This is recommended unless you need a specific model. This is the default behavior.\n- `flux-2-klein` - from 5 credits/image\n - Supported resolutions: 640px, 1k, 2k\n - Available for tiers: free, creator, pro, business\n - Image count allowed: 1\n- `flux-schnell` - from 5 credits/image\n - Supported resolutions: 640px, 1k, 2k\n - Available for tiers: free, creator, pro, business\n - Image count allowed: 1, 2, 3, 4\n- `gpt-image-2` - from 50 credits/image\n - Supported resolutions: 640px, 1k, 2k, 4k\n - Available for tiers: creator, pro, business\n - Image count allowed: 1, 2, 3, 4\n- `gpt-image-2.5-flare` - from 100 credits/image\n - Supported resolutions: 640px, 1k, 2k, 4k\n - Available for tiers: creator, pro, business\n - Image count allowed: 1, 2, 3, 4\n- `krea-2` - from 10 credits/image\n - Supported resolutions: 640px, 1k\n - Available for tiers: free, creator, pro, business\n - Image count allowed: 1\n- `nano-banana` - from 50 credits/image\n - Supported resolutions: 640px, 1k\n - Available for tiers: creator, pro, business\n - Image count allowed: 1, 2, 3, 4\n- `nano-banana-2` - from 100 credits/image\n - Supported resolutions: 640px, 1k, 2k, 4k\n - Available for tiers: creator, pro, business\n - Image count allowed: 1, 4, 9, 16\n- `nano-banana-2-lite` - from 50 credits/image\n - Supported resolutions: 640px, 1k\n - Available for tiers: creator, pro, business\n - Image count allowed: 1, 2, 3, 4\n- `nano-banana-2.1` - from 50 credits/image\n - Supported resolutions: 640px, 1k, 2k, 4k\n - Available for tiers: creator, pro, business\n - Image count allowed: 1, 4, 9, 16\n- `nano-banana-pro` - from 150 credits/image\n - Supported resolutions: 1k, 2k, 4k\n - Available for tiers: creator, pro, business\n - Image count allowed: 1, 4, 9, 16\n- `qwen-image-2.1` - from 10 credits/image\n - Supported resolutions: 640px, 1k, 2k\n - Available for tiers: free, creator, pro, business\n - Image count allowed: 1, 2, 3, 4\n- `seedream-v4` - from 40 credits/image\n - Supported resolutions: 640px, 1k, 2k, 4k\n - Available for tiers: creator, pro, business\n - Image count allowed: 1, 2, 3, 4\n- `seedream-v5-pro` - from 75 credits/image\n - Supported resolutions: 640px, 1k, 2k\n - Available for tiers: creator, pro, business\n - Image count allowed: 1, 2, 3, 4\n- `z-image-turbo` - from 5 credits/image\n - Supported resolutions: 640px, 1k, 2k\n - Available for tiers: free, creator, pro, business\n - Image count allowed: 1, 2, 3, 4\n\n**Deprecated Enum Values:**\n- `seedream` - Use `seedream-v4` instead.\n" }, "nullable": true, "handle": "model", "value": null }, { "description": "The aspect ratio of the output image(s). If not specified, defaults to `1:1` (square).", "jsonSchema": { "type": "string", "enum": [ "1:1", "16:9", "9:16" ], "description": "The aspect ratio of the output image(s). If not specified, defaults to `1:1` (square)." }, "nullable": true, "handle": "aspect_ratio", "value": null }, { "description": "Maximum resolution (longest edge) for the output image.\n\n**Options:**\n- `640px` — up to 640px\n- `1k` — up to 1024px\n- `2k` — up to 2048px\n- `4k` — up to 4096px\n- `auto` — **Deprecated.** Mapped server-side from your subscription tier to the best matching resolution the model supports\n\n**Per-model support:**\n- `flux-2-klein` - 640px, 1k, 2k\n- `flux-schnell` - 640px, 1k, 2k\n- `gpt-image-2` - 640px, 1k, 2k, 4k\n- `gpt-image-2.5-flare` - 640px, 1k, 2k, 4k\n- `krea-2` - 640px, 1k\n- `nano-banana` - 640px, 1k\n- `nano-banana-2` - 640px, 1k, 2k, 4k\n- `nano-banana-2-lite` - 640px, 1k\n- `nano-banana-2.1` - 640px, 1k, 2k, 4k\n- `nano-banana-pro` - 1k, 2k, 4k\n- `qwen-image-2.1` - 640px, 1k, 2k\n- `seedream-v4` - 640px, 1k, 2k, 4k\n- `seedream-v5-pro` - 640px, 1k, 2k\n- `z-image-turbo` - 640px, 1k, 2k\n\nNote: Resolution availability depends on the model and your subscription tier.", "jsonSchema": { "type": "string", "enum": [ "auto", "640px", "1k", "2k", "4k" ], "description": "Maximum resolution (longest edge) for the output image.\n\n**Options:**\n- `640px` — up to 640px\n- `1k` — up to 1024px\n- `2k` — up to 2048px\n- `4k` — up to 4096px\n- `auto` — **Deprecated.** Mapped server-side from your subscription tier to the best matching resolution the model supports\n\n**Per-model support:**\n- `flux-2-klein` - 640px, 1k, 2k\n- `flux-schnell` - 640px, 1k, 2k\n- `gpt-image-2` - 640px, 1k, 2k, 4k\n- `gpt-image-2.5-flare` - 640px, 1k, 2k, 4k\n- `krea-2` - 640px, 1k\n- `nano-banana` - 640px, 1k\n- `nano-banana-2` - 640px, 1k, 2k, 4k\n- `nano-banana-2-lite` - 640px, 1k\n- `nano-banana-2.1` - 640px, 1k, 2k, 4k\n- `nano-banana-pro` - 1k, 2k, 4k\n- `qwen-image-2.1` - 640px, 1k, 2k\n- `seedream-v4` - 640px, 1k, 2k, 4k\n- `seedream-v5-pro` - 640px, 1k, 2k\n- `z-image-turbo` - 640px, 1k, 2k\n\nNote: Resolution availability depends on the model and your subscription tier." }, "nullable": true, "handle": "resolution", "value": null }, { "description": "The art style to use for image generation.", "jsonSchema": { "type": "object", "properties": { "prompt": { "type": "string", "minLength": 1, "description": "The prompt used for the image(s)." }, "tool": { "type": "string", "enum": [ "ai-anime-generator", "ai-art-generator", "ai-background-generator", "ai-character-generator", "ai-face-generator", "ai-fashion-generator", "ai-icon-generator", "ai-illustration-generator", "ai-interior-design-generator", "ai-landscape-generator", "ai-logo-generator", "ai-manga-generator", "ai-outfit-generator", "ai-pattern-generator", "ai-photo-generator", "ai-sketch-generator", "ai-tattoo-generator", "album-cover-generator", "animated-characters-generator", "architecture-generator", "book-cover-generator", "comic-book-generator", "dark-fantasy-ai", "disney-ai-generator", "dnd-ai-art-generator", "emoji-generator", "fantasy-map-generator", "graffiti-generator", "movie-poster-generator", "optical-illusion-generator", "pokemon-generator", "south-park-character-generator", "superhero-generator", "thumbnail-maker", "general" ], "description": "The art style to use for image generation. Defaults to 'general' if not provided." } }, "required": [ "prompt" ], "additionalProperties": true, "description": "The art style to use for image generation." }, "nullable": false, "handle": "style" } ], "outputs": [ { "description": "Success", "jsonSchema": { "type": "object", "properties": { "id": { "type": "string", "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." } }, "required": [ "id", "credits_charged" ], "additionalProperties": true, "description": "Success" }, "nullable": false, "handle": "output" } ], "name": "Generate the image", "executor": { "kind": "connector", "action": "magichour.create_ai_image_generator", "outputMode": "value" } } }, "n_00866343508aa956": { "inputs": { "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_792b5a2dcb058dc8", "output": "output" } ] } }, "name": "Read the image project ID", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "object", "properties": { "id": { "type": "string", "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." } }, "required": [ "id", "credits_charged" ], "additionalProperties": true, "description": "Success" }, "nullable": false, "handle": "body" } ], "outputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "id" } ], "name": "Read the image project ID", "moduleId": "n_b723bdd100fcfb65", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_bc722538c8e8470d": { "inputs": {}, "name": "Wait for the image", "kind": "wait", "inputDefinitions": [], "prompt": "Wait for the image", "autoContinue": { "kind": "after", "durationMs": 10000 } }, "n_0587556c6f0ee60a": { "inputs": { "id": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_00866343508aa956", "output": "id" } ] } }, "name": "Check the image project", "kind": "task", "task": { "inputs": [ { "description": "Unique ID of the image project. This value is returned by all of the POST APIs that create an image.", "jsonSchema": { "type": "string", "description": "Unique ID of the image project. This value is returned by all of the POST APIs that create an image." }, "nullable": false, "handle": "id" } ], "outputs": [ { "description": "Success", "jsonSchema": { "type": "object", "properties": { "id": { "type": "string", "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." }, "status": { "type": "string", "enum": [ "draft", "queued", "rendering", "complete", "error", "canceled" ], "description": "The status of the image.\n\n- `draft` - the project was created but has not been submitted for rendering\n- `queued` - the job is waiting for an available server\n- `rendering` - the job is being processed; the `image.started` webhook event fires when rendering begins\n- `complete` - the job finished successfully; fires `image.completed`\n- `error` - the job failed during processing; fires `image.errored`\n- `canceled` - the job was manually canceled (for example from the Magic Hour web app)\n\n**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." }, "type": { "type": "string", "description": "The type of the image project. Possible values are FACE_EDITOR, AI_IMAGE_EDITOR, GENERATIVE_FILL, 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, IMAGE_COLOR_GRADER, HEAD_SWAP, BODY_SWAP, STORYBOARD, IMAGE_EXPANDER" }, "created_at": { "type": "string", "format": "date-time", "description": "Created at." }, "enabled": { "type": "boolean", "description": "Whether this resource is active. If false, it is deleted." }, "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." }, "downloads": { "type": "array", "items": { "type": "object", "properties": { "url": { "type": "string", "format": "uri", "description": "Url." }, "expires_at": { "type": "string", "format": "date-time", "description": "Expires at." } }, "required": [ "url", "expires_at" ], "additionalProperties": true, "description": "The download URL and expiration time of the project." }, "description": "Downloads." }, "error": { "type": [ "object", "null" ], "properties": { "message": { "type": "string", "description": "Details on the reason why a failure happened." }, "code": { "type": "string", "description": "An error code to indicate why a failure happened." } }, "required": [ "message", "code" ], "additionalProperties": true, "description": "The error reported while rendering the project." }, "image_count": { "type": "integer", "description": "Number of images generated" } }, "required": [ "id", "name", "status", "type", "created_at", "enabled", "credits_charged", "downloads", "error", "image_count" ], "additionalProperties": true, "description": "Success" }, "nullable": false, "handle": "output" } ], "name": "Check the image project", "executor": { "kind": "connector", "action": "magichour.get_image_projects", "outputMode": "value" } } }, "n_a4e4044617c65c61": { "inputs": { "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_0587556c6f0ee60a", "output": "output" } ] }, "projectId": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_00866343508aa956", "output": "id" } ] }, "previous": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_a4e4044617c65c61", "output": "state" } ] } }, "name": "Check image status", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "object", "properties": { "id": { "type": "string", "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." }, "status": { "type": "string", "enum": [ "draft", "queued", "rendering", "complete", "error", "canceled" ], "description": "The status of the image.\n\n- `draft` - the project was created but has not been submitted for rendering\n- `queued` - the job is waiting for an available server\n- `rendering` - the job is being processed; the `image.started` webhook event fires when rendering begins\n- `complete` - the job finished successfully; fires `image.completed`\n- `error` - the job failed during processing; fires `image.errored`\n- `canceled` - the job was manually canceled (for example from the Magic Hour web app)\n\n**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." }, "type": { "type": "string", "description": "The type of the image project. Possible values are FACE_EDITOR, AI_IMAGE_EDITOR, GENERATIVE_FILL, 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, IMAGE_COLOR_GRADER, HEAD_SWAP, BODY_SWAP, STORYBOARD, IMAGE_EXPANDER" }, "created_at": { "type": "string", "format": "date-time", "description": "Created at." }, "enabled": { "type": "boolean", "description": "Whether this resource is active. If false, it is deleted." }, "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." }, "downloads": { "type": "array", "items": { "type": "object", "properties": { "url": { "type": "string", "format": "uri", "description": "Url." }, "expires_at": { "type": "string", "format": "date-time", "description": "Expires at." } }, "required": [ "url", "expires_at" ], "additionalProperties": true, "description": "The download URL and expiration time of the project." }, "description": "Downloads." }, "error": { "type": [ "object", "null" ], "properties": { "message": { "type": "string", "description": "Details on the reason why a failure happened." }, "code": { "type": "string", "description": "An error code to indicate why a failure happened." } }, "required": [ "message", "code" ], "additionalProperties": true, "description": "The error reported while rendering the project." }, "image_count": { "type": "integer", "description": "Number of images generated" } }, "required": [ "id", "name", "status", "type", "created_at", "enabled", "credits_charged", "downloads", "error", "image_count" ], "additionalProperties": true, "description": "Success" }, "nullable": false, "handle": "body" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "projectId" }, { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": true, "handle": "previous" } ], "outputs": [ { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "state" }, { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "done" }, { "jsonSchema": { "type": "string", "minLength": 1, "description": "The photo URL or existing Telegram file_id to send." }, "nullable": false, "handle": "url" } ], "name": "Check image status", "moduleId": "n_b2424c727369d251", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_810d3562cdbb171b": { "inputs": {}, "name": "Image complete?", "kind": "condition", "matchMode": "first", "cases": [ { "output": "send", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_a4e4044617c65c61", "output": "done" } }, "operator": "isTrue" } ] } ] } ] }, "n_1f5aa0cb2b9884a3": { "inputs": { "chatId": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_cb6f0970d983220d", "output": "chatId" } ] }, "photo": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_a4e4044617c65c61", "output": "url" } ] } }, "name": "Send the image to Telegram", "kind": "task", "task": { "inputs": [ { "description": "The target Telegram chat ID or channel username.", "jsonSchema": { "anyOf": [ { "type": "integer", "description": "A union variant." }, { "type": "string", "pattern": "^-?\\d+$", "description": "A numeric Telegram chat identifier encoded as a string." }, { "type": "string", "pattern": "^@[A-Za-z0-9_]+$", "description": "A Telegram @username that identifies a public chat or channel." } ], "description": "The target Telegram chat ID or channel username." }, "nullable": false, "handle": "chatId" }, { "description": "The photo URL or existing Telegram file_id to send.", "jsonSchema": { "type": "string", "minLength": 1, "description": "The photo URL or existing Telegram file_id to send." }, "nullable": false, "handle": "photo" }, { "description": "The caption for the photo.", "jsonSchema": { "type": "string", "maxLength": 1024, "description": "The caption for the photo." }, "nullable": true, "handle": "caption", "value": null }, { "description": "The parse mode used for message entities.", "jsonSchema": { "type": "string", "enum": [ "Markdown", "MarkdownV2", "HTML" ], "description": "The parse mode used for message entities." }, "nullable": true, "handle": "parseMode", "value": null }, { "description": "Whether to send the photo silently.", "jsonSchema": { "type": "boolean", "description": "Whether to send the photo silently." }, "nullable": true, "handle": "disableNotification", "value": null }, { "description": "Whether to protect the photo from forwarding and saving.", "jsonSchema": { "type": "boolean", "description": "Whether to protect the photo from forwarding and saving." }, "nullable": true, "handle": "protectContent", "value": null }, { "description": "The forum topic ID for the target message thread.", "jsonSchema": { "type": "integer", "exclusiveMinimum": 0, "description": "The forum topic ID for the target message thread." }, "nullable": true, "handle": "messageThreadId", "value": null }, { "description": "The message ID to reply to.", "jsonSchema": { "type": "integer", "exclusiveMinimum": 0, "description": "The message ID to reply to." }, "nullable": true, "handle": "replyToMessageId", "value": null } ], "outputs": [ { "description": "The unique message identifier inside the chat.", "jsonSchema": { "type": "integer", "description": "The unique message identifier inside the chat." }, "nullable": false, "handle": "messageId" }, { "description": "The Unix timestamp when the message was sent.", "jsonSchema": { "type": "integer", "description": "The Unix timestamp when the message was sent." }, "nullable": false, "handle": "date" }, { "description": "The chat the message belongs to.", "jsonSchema": { "type": "object", "properties": { "id": { "type": "integer", "description": "The unique identifier of the chat." }, "type": { "type": "string", "description": "The chat type, such as private, group, supergroup, or channel." }, "title": { "type": "string", "description": "The chat title for groups, supergroups, and channels." }, "username": { "type": "string", "description": "The public username of the chat, when available." }, "firstName": { "type": "string", "description": "The first name for a private chat counterpart." }, "lastName": { "type": "string", "description": "The last name for a private chat counterpart." }, "isForum": { "type": "boolean", "description": "Whether the supergroup chat is a forum." } }, "required": [ "id", "type" ], "additionalProperties": false, "description": "The chat the message belongs to." }, "nullable": false, "handle": "chat" }, { "description": "The sender of the message.", "jsonSchema": { "type": "object", "properties": { "id": { "type": "integer", "description": "The unique identifier of the user or bot." }, "isBot": { "type": "boolean", "description": "Whether this account is a bot." }, "firstName": { "type": "string", "description": "The first name of the user or bot." }, "username": { "type": "string", "description": "The username of the user or bot." }, "languageCode": { "type": "string", "description": "The IETF language tag of the user." }, "canJoinGroups": { "type": "boolean", "description": "Whether the bot can be invited to groups." }, "canReadAllGroupMessages": { "type": "boolean", "description": "Whether privacy mode is disabled for the bot." }, "supportsInlineQueries": { "type": "boolean", "description": "Whether the bot supports inline queries." }, "canConnectToBusiness": { "type": "boolean", "description": "Whether the bot can be connected to a Telegram Business account." }, "hasMainWebApp": { "type": "boolean", "description": "Whether the bot has a main Web App configured." } }, "required": [ "id", "isBot", "firstName" ], "additionalProperties": false, "description": "The sender of the message." }, "nullable": true, "handle": "from" }, { "description": "The chat on behalf of which the message was sent.", "jsonSchema": { "type": "object", "properties": { "id": { "type": "integer", "description": "The unique identifier of the chat." }, "type": { "type": "string", "description": "The chat type, such as private, group, supergroup, or channel." }, "title": { "type": "string", "description": "The chat title for groups, supergroups, and channels." }, "username": { "type": "string", "description": "The public username of the chat, when available." }, "firstName": { "type": "string", "description": "The first name for a private chat counterpart." }, "lastName": { "type": "string", "description": "The last name for a private chat counterpart." }, "isForum": { "type": "boolean", "description": "Whether the supergroup chat is a forum." } }, "required": [ "id", "type" ], "additionalProperties": false, "description": "The chat on behalf of which the message was sent." }, "nullable": true, "handle": "senderChat" }, { "description": "The UTF-8 text of the message, for text messages.", "jsonSchema": { "type": "string", "description": "The UTF-8 text of the message, for text messages." }, "nullable": true, "handle": "text" }, { "description": "The caption for media messages.", "jsonSchema": { "type": "string", "description": "The caption for media messages." }, "nullable": true, "handle": "caption" }, { "description": "The available sizes for an attached photo.", "jsonSchema": { "type": "array", "items": { "type": "object", "properties": { "fileId": { "type": "string", "description": "The file identifier used to download or reuse the photo." }, "fileUniqueId": { "type": "string", "description": "The stable unique identifier of the photo." }, "width": { "type": "integer", "description": "The photo width in pixels." }, "height": { "type": "integer", "description": "The photo height in pixels." }, "fileSize": { "type": "integer", "description": "The photo file size in bytes." } }, "required": [ "fileId", "fileUniqueId", "width", "height" ], "additionalProperties": false, "description": "A Telegram photo size record." }, "description": "The available sizes for an attached photo." }, "nullable": true, "handle": "photo" }, { "description": "The attached document, when present.", "jsonSchema": { "type": "object", "properties": { "fileId": { "type": "string", "description": "The file identifier used to download or reuse the document." }, "fileUniqueId": { "type": "string", "description": "The stable unique identifier of the document." }, "fileName": { "type": "string", "description": "The original filename of the document." }, "mimeType": { "type": "string", "description": "The MIME type of the document." }, "fileSize": { "type": "integer", "description": "The document size in bytes." } }, "required": [ "fileId", "fileUniqueId" ], "additionalProperties": false, "description": "The attached document, when present." }, "nullable": true, "handle": "document" }, { "description": "The attached location, when present.", "jsonSchema": { "type": "object", "properties": { "latitude": { "type": "number", "description": "The latitude of the location." }, "longitude": { "type": "number", "description": "The longitude of the location." }, "horizontalAccuracy": { "type": "number", "description": "The radius of uncertainty for the location, in meters." }, "livePeriod": { "type": "integer", "description": "The live location update period in seconds." }, "heading": { "type": "integer", "description": "The direction in which the user is moving, in degrees." }, "proximityAlertRadius": { "type": "integer", "description": "The distance in meters for proximity alerts." } }, "required": [ "latitude", "longitude" ], "additionalProperties": false, "description": "The attached location, when present." }, "nullable": true, "handle": "location" }, { "description": "The attached poll, when present.", "jsonSchema": { "type": "object", "properties": { "id": { "type": "string", "description": "The unique identifier of the poll." }, "question": { "type": "string", "description": "The poll question text." }, "options": { "type": "array", "items": { "type": "object", "properties": { "text": { "type": "string", "description": "The text of the poll option." }, "voterCount": { "type": "integer", "description": "The number of votes received by this option." } }, "required": [ "text", "voterCount" ], "additionalProperties": false, "description": "A Telegram poll option." }, "description": "The options available in the poll." }, "totalVoterCount": { "type": "integer", "description": "The total number of users that voted." }, "isClosed": { "type": "boolean", "description": "Whether the poll is closed." }, "isAnonymous": { "type": "boolean", "description": "Whether the poll is anonymous." }, "type": { "type": "string", "enum": [ "regular", "quiz" ], "description": "The type of the poll." }, "allowsMultipleAnswers": { "type": "boolean", "description": "Whether multiple answers are allowed." }, "closeDate": { "type": "integer", "description": "The Unix timestamp when the poll closes." }, "openPeriod": { "type": "integer", "description": "The amount of time in seconds the poll stays open." }, "explanation": { "type": "string", "description": "The explanation text shown for quiz polls." }, "correctOptionId": { "type": "integer", "description": "The index of the correct option for quiz polls." } }, "required": [ "id", "question", "options", "totalVoterCount", "isClosed", "isAnonymous", "type", "allowsMultipleAnswers" ], "additionalProperties": false, "description": "The attached poll, when present." }, "nullable": true, "handle": "poll" }, { "description": "The message entities parsed from the text.", "jsonSchema": { "type": "array", "items": { "type": "object", "properties": {}, "additionalProperties": true, "description": "Schema for anyObject." }, "description": "The message entities parsed from the text." }, "nullable": true, "handle": "entities" }, { "description": "The message entities parsed from the caption.", "jsonSchema": { "type": "array", "items": { "type": "object", "properties": {}, "additionalProperties": true, "description": "Schema for anyObject." }, "description": "The message entities parsed from the caption." }, "nullable": true, "handle": "captionEntities" }, { "description": "The Unix timestamp of the original forwarded message.", "jsonSchema": { "type": "integer", "description": "The Unix timestamp of the original forwarded message." }, "nullable": true, "handle": "forwardDate" }, { "description": "The original sender of a forwarded message.", "jsonSchema": { "type": "object", "properties": { "id": { "type": "integer", "description": "The unique identifier of the user or bot." }, "isBot": { "type": "boolean", "description": "Whether this account is a bot." }, "firstName": { "type": "string", "description": "The first name of the user or bot." }, "username": { "type": "string", "description": "The username of the user or bot." }, "languageCode": { "type": "string", "description": "The IETF language tag of the user." }, "canJoinGroups": { "type": "boolean", "description": "Whether the bot can be invited to groups." }, "canReadAllGroupMessages": { "type": "boolean", "description": "Whether privacy mode is disabled for the bot." }, "supportsInlineQueries": { "type": "boolean", "description": "Whether the bot supports inline queries." }, "canConnectToBusiness": { "type": "boolean", "description": "Whether the bot can be connected to a Telegram Business account." }, "hasMainWebApp": { "type": "boolean", "description": "Whether the bot has a main Web App configured." } }, "required": [ "id", "isBot", "firstName" ], "additionalProperties": false, "description": "The original sender of a forwarded message." }, "nullable": true, "handle": "forwardFrom" }, { "description": "The original chat of a forwarded message sent on behalf of a chat.", "jsonSchema": { "type": "object", "properties": { "id": { "type": "integer", "description": "The unique identifier of the chat." }, "type": { "type": "string", "description": "The chat type, such as private, group, supergroup, or channel." }, "title": { "type": "string", "description": "The chat title for groups, supergroups, and channels." }, "username": { "type": "string", "description": "The public username of the chat, when available." }, "firstName": { "type": "string", "description": "The first name for a private chat counterpart." }, "lastName": { "type": "string", "description": "The last name for a private chat counterpart." }, "isForum": { "type": "boolean", "description": "Whether the supergroup chat is a forum." } }, "required": [ "id", "type" ], "additionalProperties": false, "description": "The original chat of a forwarded message sent on behalf of a chat." }, "nullable": true, "handle": "forwardFromChat" }, { "description": "The original message ID inside the source channel.", "jsonSchema": { "type": "integer", "description": "The original message ID inside the source channel." }, "nullable": true, "handle": "forwardFromMessageId" }, { "description": "The original author signature for a forwarded post.", "jsonSchema": { "type": "string", "description": "The original author signature for a forwarded post." }, "nullable": true, "handle": "forwardSignature" }, { "description": "The display name of a forwarded sender who disallows linking.", "jsonSchema": { "type": "string", "description": "The display name of a forwarded sender who disallows linking." }, "nullable": true, "handle": "forwardSenderName" }, { "description": "The link preview options attached to the message.", "jsonSchema": { "type": "object", "properties": {}, "additionalProperties": true, "description": "The link preview options attached to the message." }, "nullable": true, "handle": "linkPreviewOptions" } ], "name": "Send the image to Telegram", "executor": { "kind": "connector", "action": "telegram.send_photo" } } }, "n_25ea8e07066139dd": { "name": "Image sent", "kind": "outputs", "outputDefs": [ { "jsonSchema": { "type": "integer", "description": "The unique message identifier inside the chat." }, "nullable": false, "handle": "messageId" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "projectId" } ], "outputMappings": { "messageId": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_1f5aa0cb2b9884a3", "output": "messageId" } ] }, "projectId": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_00866343508aa956", "output": "id" } ] } } } }, "edges": [ { "source": "n_ab9d29500cfd3df8", "target": "n_cb6f0970d983220d" }, { "source": "n_cb6f0970d983220d", "target": "n_792b5a2dcb058dc8" }, { "source": "n_792b5a2dcb058dc8", "target": "n_00866343508aa956" }, { "source": "n_00866343508aa956", "target": "n_bc722538c8e8470d" }, { "source": "n_bc722538c8e8470d", "target": "n_0587556c6f0ee60a", "sourceHandle": "continue" }, { "source": "n_0587556c6f0ee60a", "target": "n_a4e4044617c65c61" }, { "source": "n_a4e4044617c65c61", "target": "n_810d3562cdbb171b" }, { "source": "n_810d3562cdbb171b", "target": "n_1f5aa0cb2b9884a3", "sourceHandle": "send" }, { "source": "n_810d3562cdbb171b", "target": "n_bc722538c8e8470d", "sourceHandle": "otherwise" }, { "source": "n_1f5aa0cb2b9884a3", "target": "n_25ea8e07066139dd" } ] } }, "modules": { "n_f56ea5c3852b6baa": { "name": "Prepare the image prompt", "imports": [], "source": "export default function prepare({body}){const m=body?.message;if(!m||typeof m.text!=='string'||!m.text.trim()||!Number.isSafeInteger(m.chat?.id))throw Error('Send an image description as a text message');return{chatId:String(m.chat.id),style:{prompt:m.text}}}\n" }, "n_b723bdd100fcfb65": { "name": "Read the image project ID", "imports": [], "source": "export default function created({body}){if(!body||typeof body.id!=='string'||!body.id)throw Error('Missing image project ID');return{id:body.id}}" }, "n_b2424c727369d251": { "name": "Check image status", "imports": [], "source": "export default function status({body,projectId,previous}){const {id,status,downloads}=body??{};if(id!==projectId)throw Error('Project ID mismatch');const count=previous==null?1:previous.count+1;if(!Number.isInteger(count)||count>60)throw Error('Polling timed out for project '+projectId);if(status==='error'||status==='canceled')throw Error('Generation '+status+' for project '+projectId);if(status==='complete'){if(!Array.isArray(downloads)||!downloads[0]||typeof downloads[0].url!=='string'||!/^https:\\/\\/[^\\/?#@\\s]+(?:[\\/?#][^\\s]*)?$/i.test(downloads[0].url))throw Error('Missing download for project '+projectId);return{state:{count},done:true,url:downloads[0].url}}if(!['draft','queued','rendering'].includes(status))throw Error('Unexpected status for project '+projectId);if(count===60)throw Error('Polling timed out for project '+projectId);return{state:{count},done:false,url:'https://unused.invalid'}}\n" } } }, "presentation": { "designer": { "version": 1, "flow": { "direction": "vertical" } } } }