# Legnext AI — Complete Documentation > Unofficial Midjourney REST API for image and video generation — production-ready, no Discord or Midjourney account required. Base URL: `https://api.legnext.ai/api` Auth: `x-api-key` header (get your key at https://legnext.ai/dashboard) Free tier: 200 one-time credits, no credit card required Pro plan: $30/month for 33,000 credits — https://legnext.ai/#pricing This file consolidates the full Legnext AI API documentation into a single markdown document for LLM consumption. Each section is delimited by `---` and prefixed with its source URL on docs.legnext.ai. --- # Overview _Legnext AI Midjourney API features for image and video generation_ ## Image Generation & Editing ### Core Features - **[Text to Image](https://docs.legnext.ai/api-reference/image-generation/diffusion)**: Generate high-quality images from text descriptions using advanced AI models. - **[Image Editing](https://docs.legnext.ai/api-reference/image-generation/edit)**: Edit and repaint specific areas of existing images with precision control. - **[Regional Repaint](https://docs.legnext.ai/api-reference/image-generation/inpaint)**: Selectively modify regions using masks and targeted prompts. - **[Background Removal](https://docs.legnext.ai/api-reference/image-generation/remove-background)**: Automatically remove backgrounds to create clean cutouts. ### Enhancement Tools - **[Upscale](https://docs.legnext.ai/api-reference/image-generation/upscale)**: Enhance image resolution and quality with AI upscaling technology. - **[Enhance](https://docs.legnext.ai/api-reference/image-generation/enhance)**: Improve image quality, clarity, and detail at current resolution. - **[Variation](https://docs.legnext.ai/api-reference/image-generation/variation)**: Create controllable variations while maintaining composition structure. - **[Remix](https://docs.legnext.ai/api-reference/image-generation/remix)**: Transform images with new prompts and controllable intensity. ### Advanced Operations - **[Extend](https://docs.legnext.ai/api-reference/image-generation/outpaint)**: Expand images in all directions using intelligent outpainting. - **[Pan Extend](https://docs.legnext.ai/api-reference/image-generation/pan)**: Extend images in a single specified direction with precision. - **[Retexture](https://docs.legnext.ai/api-reference/image-generation/retexture)**: Transform materials and textures with AI-powered style transfer. - **[Advanced Edit](https://docs.legnext.ai/api-reference/image-generation/upload-paint)**: Complex editing with custom canvas positioning and masks. ### Utility Functions - **[Blend](https://docs.legnext.ai/api-reference/image-generation/blend)**: Combine 2-5 images into a single unique creation with seamless blending. - **[Describe](https://docs.legnext.ai/api-reference/image-generation/describe)**: Generate detailed text descriptions and prompts from existing images. - **[Shorten](https://docs.legnext.ai/api-reference/image-generation/shorten)**: Analyze and simplify prompts to their most essential elements. - **[Reroll](https://docs.legnext.ai/api-reference/image-generation/reroll)**: Re-execute tasks to generate new variations with same parameters. ## Video Generation - **[Video Diffusion](https://docs.legnext.ai/api-reference/video-generation/video-diffusion)**: Generate dynamic videos from text prompts or existing images. - **[Extend Video](https://docs.legnext.ai/api-reference/video-generation/extend-video)**: Extend existing videos with seamless continuation and motion. - **[Video Upscale](https://docs.legnext.ai/api-reference/video-generation/video-upscale)**: Enhance video resolution and quality using AI upscaling technology. ## Before You Start **Important**: Please read our [Notice](https://docs.legnext.ai/getting-started/notice) before using the API to understand supported models and current limitations. --- # Quickstart _Get started with Legnext AI API_ ## 1. Generate an API Key Get your API key from the Legnext dashboard to authenticate your requests. > **Warning:** Never share your API key with anyone. Keep it secure and never commit it to version control. ## 2. Set URL and Endpoint All API requests are made to our base URL with specific endpoints: ``` https://api.legnext.ai/api/v1/{endpoint} ``` For example: `https://api.legnext.ai/api/v1/diffusion` ## 3. Headers All API requests must include the following headers: | Header | Required | Description | |--------|----------|-------------| | `x-api-key` | Yes | Your API key for authentication | | `Content-Type` | No | Set to `application/json` | ## 4. Make Your First API Call Generate your first image using our text-to-image endpoint: ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/diffusion" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "A beautiful sunset over mountains with vibrant colors", "callback": "https://your-domain.com/webhook" }' ``` ```python Python import requests url = "https://api.legnext.ai/api/v1/diffusion" headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } data = { "text": "A beautiful sunset over mountains with vibrant colors", "callback": "https://your-domain.com/webhook" } response = requests.post(url, headers=headers, json=data) result = response.json() print(result) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/diffusion', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ text: 'A beautiful sunset over mountains with vibrant colors', callback: 'https://your-domain.com/webhook' }) }); const result = await response.json(); console.log(result); ``` ## 5. Response Format All endpoints return a Job object containing: - `job_id`: Unique job identifier - `status`: Processing status (pending, processing, completed, failed) - `output`: Contains result image URLs when completed - `meta`: Usage and timing information - `error`: Error details if task failed ## 6. Error Codes & Handling When a request fails, the API returns an HTTP error status code along with an error object: ```json { "code": 401, "message": "Failed to verify api key", "raw_message": "", "detail": null } ``` ### HTTP Status Codes | Code | Description | Solution | |------|-------------|----------| | `400` | Bad Request | Invalid request parameters or malformed request body. Check your input parameters | | `401` | Unauthorized | Authentication failed. Verify your API key is valid and included in the `x-api-key` header | | `402` | Payment Required | Insufficient credits in your account. Top up your balance or upgrade your plan | | `403` | Forbidden | Sensitive content detected or permission denied. Review content policy guidelines | | `413` | Payload Too Large | File size exceeds maximum limit. Reduce file size and try again | | `422` | Unprocessable Entity | Invalid parameter values or validation failed. Check parameter formats and values | | `429` | Too Many Requests | Rate limit exceeded. Reduce request frequency or upgrade your plan | | `500` | Internal Server Error | Temporary server issue. The request will be automatically retried | > **Tip:** All error responses include a `code` field matching the HTTP status code and a `message` field with a human-readable description. Check these fields to understand what went wrong. ## 7. Next Steps - Explore our [comprehensive endpoint documentation](https://docs.legnext.ai/api-reference/image-generation/diffusion) for detailed parameters and examples - Learn about [task status checking](https://docs.legnext.ai/api-reference/task-management/get-task) for monitoring your requests - Browse all available [image and video generation features](https://docs.legnext.ai/getting-started/overview) Start exploring our powerful image generation capabilities! ## Important Please read our [Notice](https://docs.legnext.ai/getting-started/notice) before using the API to understand supported models and current limitations. --- # Important Information _API requirements, limitations, and supported models_ ## Supported Models The API currently supports the following models: - **v6** - **v6.1** - **niji 6** - **v7** (default) - **v8** — add `--v 8` to your prompt. Premium tier with `--hd`, `--q 4`, and `--sv 6` (4x cost). [Sunsetting soon — see below.] - **v8.1** — add `--v 8.1` to your prompt. HD by default at standard cost. Pro subscription required. > **Warning:** Midjourney plans to sunset **v8.0** approximately 2 weeks after v8.1 stabilizes. We recommend migrating `--v 8` prompts to `--v 8.1` ahead of time. ## Current Limitations The API currently does **not** support the following features: - `--repeat` parameter - `--personalize` parameter - `{}` prompt arrangement syntax - `--stealth`/`--public` parameters ## Important Usage Requirements - **When using enhance**: The original job must be created in draft mode with parameters `--v7 --draft` - **Draft mode**: Ultra-fast image prototyping (10x faster than normal mode) with slightly reduced quality but consuming only half the GPU resources. Use `--draft` parameter to activate. ## Supported Speed Modes Speed modes control the GPU type used for task execution, determining task execution time. The API provides **fast mode** and **turbo mode**, with **relax mode** currently not supported. ### Fast Mode (`--fast`) Fast mode is the default GPU speed mode where API requests are prioritized using GPU resources for processing. Usually completes image generation within 1 minute. - **Usage**: Activated with `--fast` parameter - **Default**: Used when no speed mode is specified - **Processing Time**: Typically under 1 minute for standard images ### Turbo Mode (`--turbo`) Turbo mode uses a high-performance GPU pool with processing speeds up to 4x faster than fast mode. This mode consumes double the GPU time quota and only supports v5 and above versions. - **Usage**: Activated with `--turbo` parameter - **Speed**: Up to 4x faster than fast mode - **Requirements**: Only supports v5+ versions - **Cost**: Consumes double GPU time quota - **Status**: Experimental feature - availability and billing may change ### Factors Affecting Task Time - **Image Resolution**: Higher resolution images require more processing time - **Aspect Ratio**: Non-standard ratios may increase processing time - **Model Version**: Newer models are typically faster - **Task Type**: Generation variations or lower quality settings reduce time - **Image Prompts**: Number of referenced images in prompts affects processing time --- # Model Information _Complete guide to Midjourney model versions including v6, v6.1, v7, and niji 6 - features, capabilities, and parameter support for each version_ The API provides multiple model version options covering the v6 series, v7 series, and niji series. Each model version has unique advantages in image generation quality, feature characteristics, and parameter support. **Supported Models**: The API currently supports models **v6**, **v6.1**, **niji 6**, **v7**, **v8**, and **v8.1**, with **v7** as the default. ## Version 8.1 🆕 Version 8.1 (alpha launched April 14, 2026) refines V8 with HD output by default, restored image prompting, and improved speed. Add `--v 8.1` to your prompt to use it. > **Note:** Midjourney plans to sunset V8.0 approximately 2 weeks after V8.1 stabilizes. We recommend migrating `--v 8` prompts to `--v 8.1` ahead of time. ### Key Improvements over V8.0 - **HD by default**: Native 2K resolution out of the box — no `--hd` flag needed - **~40% faster than V8 HD**: V8.1 HD generates at roughly the speed V8 SD did - **Same price as V8 SD**: V8.1 is a flat 1x credits — there is no premium tier - **Image prompts and image weights restored**: V8.1 supports image URLs in the prompt plus `--iw` for weighting (these were unavailable in early V8.0) - **Prompt Shortener**: Prompts that exceed length limits are automatically shortened by Midjourney before generation - **Improved Describe**: Longer, more detailed prompt descriptions match V8's prompting style ### V8.1 Parameters - `--ar` — aspect ratio - `--s` / `--stylize` — stylization strength (0–1000) - `--c` / `--chaos` — variability (0–100) - `--w` / `--weird` — weirdness (0–3000) - `--raw` / `--style raw` — reduced default styling - `--exp` — experimental aesthetic - `--sref` + `--sw` — style reference URLs and weight - `--p` — personalization code - `--iw` — image weight (with image URLs in prompt) - Moodboards ### V8.1 Cost Model - All V8.1 generations: **1x credits** (80 points / $0.08 per task) - No premium tier — `--hd`, `--q`, and `--sv 6` either don't apply or are rejected - Subscription required: **Developer (Pro) plan or above** — same as V8 - Turbo mode (`--turbo`) is **not supported** ### Removed in V8.1 (will be rejected) | Removed Parameter | Why | |---|---| | `--q` / `--quality` | V8.1 has no quality tiers; HD is default | | `--cref` / `--cw` | Not supported in V8.1 alpha | | `--oref` / `--ow` | Not supported in V8.1 alpha | | `--no` | Negative prompt is not supported in V8.1 alpha | | `--turbo` | V8 family does not support Turbo mode | | `--sd` | SD output is controlled via the web settings panel, not the API | | `--hd` | Accepted but treated as a no-op (HD is already the default) | Requests containing rejected flags receive an HTTP 400 with a message naming the offending flag. ### Feature Support | Feature | v8 | v8.1 | |---------|-----|------| | Variation | Strong & Subtle | Strong & Subtle | | Reroll | ✓ | ✓ | | Remix | ✓ | ✓ | | Animate (image to video) | ✓ | ✓ | | Blend | ✓ (V8 native) | ✓ | | Image Prompt + `--iw` | Limited | ✓ (restored) | | Style Reference (`--sref` / `--sw`) | ✓ | ✓ | | Personalization (`--p`) | ✓ | ✓ | | Describe | via V7 fallback | via V7 fallback | | Inpaint / Outpaint / Pan | Not available | Not available | ## Version 8 Version 8 (alpha launched March 17, 2026) is a generational leap in AI image generation. Add `--v 8` to your prompt to use it. > **Warning:** Midjourney plans to sunset V8.0 approximately 2 weeks after V8.1 stabilizes. New integrations should target `--v 8.1`. ### Key Improvements - **~5x faster generation**: Standard images complete in under 15 seconds - **Native 2K HD resolution**: Use `--hd` for natively rendered 2K images — no upscale needed - **Dramatically better text rendering**: Wrap text in `"quotes"` for readable signs, labels, and typography - **Accurate hands & anatomy**: Correct finger counts, natural proportions, consistent full-body poses - **Superior prompt adherence**: Complex multi-element compositions render with much higher fidelity - **Enhanced coherence**: `--q 4` mode maintains visual consistency in complex scenes - **Physically accurate lighting**: Reflections, subsurface scattering, and shadow direction are physically grounded ### V8 Parameters - `--hd` — Native 2K resolution (4x cost) - `--q 4` — Enhanced coherence mode (4x cost) - `--oref` — Omni Reference, replaces `--cref` (handles both person likeness and object form) - `--sv 6` — Use old (more accurate) SREF version (4x cost) - All V7 parameters (`--chaos`, `--weird`, `--exp`, `--raw`, `--sref`, `--stylize`, etc.) are supported ### V8 Cost Model - Standard V8 generation: **same cost as V7** - Premium features (`--hd`, `--q 4`, `--sv 6`): **4x cost** - V8 does **not** require upscaling — images are natively high resolution - Turbo mode (`--turbo`) is **not supported** with V8 ### Feature Support | Feature | v7 | v8 | |---------|-----|-----| | Variation | Strong & Subtle | Strong & Subtle | | Upscale | Subtle & Creative | Not needed (native 2K) | | Reroll | ✓ | ✓ | | Remix | ✓ | ✓ | | Animate (image to video) | ✓ | ✓ | | Blend | ✓ | ✓ (V8 native) | | Inpaint / Outpaint / Pan | ✓ | Not available | | Style Reference (--sref) | ✓ | ✓ (higher fidelity) | | Personalization (--p) | ✓ | ✓ (backward compatible) | ## Version 7 Version 7 (released April 3, 2025) achieved significant breakthroughs in image generation. This version dramatically improved the processing accuracy of text and image prompts, while achieving a qualitative leap in image quality—particularly in human anatomy, hand details, and object textures. As core innovations, V7 introduces two revolutionary features: - **Draft Mode**: Supports rapid iterative generation - **Universal Reference**: Provides more powerful image reference capabilities, bringing new possibilities to creative workflows ### Feature Support | Feature | v6* | v7* | |---------|-----|-----| | Variation | Strong & Subtle | Strong & Subtle | | Upscale | Subtle & Creative | Same as v6.1 | | Extend | ✓ | Same as v6.1 | | Outpaint | ✓ | Same as v6.1 | | Reshape | ✓ | ✓ | | Moodboard | ✓ | ✓ | | Edit | ✓ | Same as v6.1 | | Advanced Edit | ✓ | ✓ | The quality parameter in V7 works differently. Please refer to the [Quality Parameter Documentation] for details. ## Version 6.1 Version 6.1 was released on July 30, 2024, as the current default model. It generates images with more coherent effects, more precise details and textures, and is approximately 25% faster than version 6. ## Version 6 Version 6 was released on December 20, 2023, and served as the default model from February 14 to July 30, 2024. Version 6 enhanced prompt accuracy for longer inputs, improved coherence and knowledge, and provided advanced image prompting and mixing capabilities. ## Niji 6 The Niji model is a special series within the platform, developed in collaboration with Spellbrush, focusing on Eastern and anime aesthetics and illustration styles. Niji 6 was released on June 7, 2024, with improved Japanese text rendering capabilities, efficient processing of short Japanese text, and even the ability to render simple Chinese characters. It provides better image details, particularly in elements like anime eye structures, and resolves some minor image defects that affected a small portion of previously generated images. ## Model Parameter Comparison The following table provides a detailed comparison of the parameters supported by each model version and their value ranges: | Parameter | v6 | v6.1 | v7 | v8 | v8.1 | niji 6 | Video Model | |:----------|:---|:---- |:---|:---|:-----|:-------|:------------| | **Original Mode** | raw | raw | raw | raw | raw | raw | raw | | **Tile** | true/false | true/false | true/false | true/false | true/false | true/false | 🚫 | | **Chaos** | 0-100 | 0-100 | 0-100 | 0-100 | 0-100 | 0-100 | 🚫 | | **Seed** | 0-4294967295 | 0-4294967295 | 0-4294967295 | 0-4294967295 | 0-4294967295 | 0-4294967295 | 🚫 | | **Stop** | 10-100 | 10-100 | 10-100 | 🚫 | 🚫 | 10-100 | 🚫 | | **Weird** | 0-3000 | 0-3000 | 0-3000 | 0-3000 | 0-3000 | 0-3000 | 🚫 | | **Stylize** | 0-1000 | 0-1000 | 0-1000 | 0-1000 | 0-1000 | 0-1000 | 🚫 | | **Quality** | (1, 2) | (0.5, 1, 2) | (1, 2, 4) | (1, 4) | 🚫 (removed) | (0.5, 1, 2) | 🚫 | | **HD Mode** | 🚫 | 🚫 | 🚫 | ✓ (4x cost) | Default (no flag) | 🚫 | 🚫 | | **Fast Mode** | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | **Turbo Mode** | ✓ | ✓ | ✓ | 🚫 | 🚫 | ✓ | ✓ | | **Relax Mode** | 🚫 | 🚫 | 🚫 | 🚫 | 🚫 | 🚫 | 🚫 | | **Image Weight** | 0-3 | 0-3 | 0-3 | 0-3 | 0-3 | 0-3 | 🚫 | | **Negative Prompt (--no)** | 🚫 | ✓ | ✓ | ✓ | 🚫 (removed) | 🚫 | 🚫 | | **Style Reference** | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 🚫 | | **Omni Reference (--oref)** | 🚫 | 🚫 | ✓ | ✓ | 🚫 (removed) | 🚫 | 🚫 | | **Character Reference (--cref)** | ✓ | ✓ | ✓ | Replaced by --oref | 🚫 (removed) | ✓ | 🚫 | | **Style Version (--sv)** | (1, 2, 3, 4) | (1, 2, 3, 4) | (1, 2, 3, 4) | 6 (legacy, 4x cost) | (1, 2, 3, 4) | (1, 2, 3, 4) | 🚫 | | **Style Weight** | 0-1000 | 0-1000 | 0-1000 | 0-1000 | 0-1000 | 0-1000 | 🚫 | | **Draft** | 🚫 | 🚫 | ✓ | 🚫 | 🚫 | 🚫 | 🚫 | | **Experimental** | 🚫 | 🚫 | 0-100 | ✓ | ✓ | 🚫 | 🚫 | | **Personalization (--p)** | 🚫 | 🚫 | ✓ | ✓ (V7 compatible) | ✓ (V7 compatible) | 🚫 | 🚫 | | **Upscale** | Subtle & Creative | Subtle & Creative | Subtle & Creative | Not needed (native 2K) | Not needed (native 2K) | Subtle & Creative | 🚫 | ## Notes: 1. ✓ indicates support for this parameter 🚫 indicates no support for this parameter 2. v8 model: `--hd` renders natively at 2K resolution (no upscale needed). `--hd`, `--q 4`, and `--sv 6` each cost 4x credits. Turbo mode is not supported. 3. v8.1 model: HD is the default — no `--hd` flag needed. All v8.1 generations are 1x credits with no premium tier. The `--q`, `--cref` / `--cw`, `--oref` / `--ow`, and `--no` parameters are removed and will be rejected. 4. v7 model exclusive parameters: draft (Draft Mode), oref (Universal Reference), ow (Universal Reference Weight), and exp (Experimental Parameters) 5. v8 replaces `--cref` (Character Reference) with `--oref` (Omni Reference) which handles both person likeness and object form 6. Video model exclusive parameters: video (Video Mode), motion (Motion Mode), end (Video End Frame), and loop (Video Loop) 7. v6.1, v7, and v8 models support the no parameter (negative prompts); v8.1 removes it --- # Image Parameters _Comprehensive reference for image generation parameters including aspect ratio, style, quality, chaos, and version control for Midjourney API_ Control various parameter settings for image generation to help you create ideal image effects. ## Image Generation Parameter List | Parameter | Format | Values/Range | Description | |--------------------------|---------------------------|---------------------------|--------------------------------------------------------------------------------| | Aspect Ratio | `--aspect`, `--ar` | Any ratio (e.g. 16:9, 2:3) | Images are initially square, but you can use the aspect ratio parameter to change this | | Chaos | `--chaos`, `--c` | 0-100 (default: 0) | Use the chaos parameter to add variety to your image results. Higher values create more unusual results | | Character Reference | `--cref` | Image URL | Want to use the same character across multiple images and scenes? You can provide character reference! **Removed in V8.1** | | Negative Prompt | `--no` | Text description | Use the negative parameter to tell what you don't want to see in the image. **Removed in V8.1** | | Quality | `--quality`, `--q` | 0.25, 0.5, 1, 2, 4 (default: 1) | Use the quality parameter to control image detail and processing time. V8 supports --q 4 for enhanced coherence (4x cost). **Removed in V8.1** | | Seed | `--seed` | 0-4294967295 | Use the seed parameter for testing and experimentation. Same seed with same prompt = consistent results | | Stop | `--stop` | 10-100 (default: 100) | Need a softer, more unique look? Use the stop parameter to finish images halfway through the process | | Raw Mode | `--raw` | No value | Use raw mode to get more control over your images, reduces default aesthetic styling | | Stylize | `--stylize`, `--s` | 0-1000 (default: 100) | Use the stylize parameter to control artistic style in images. Lower = more prompt-focused, Higher = more artistic | | Style Reference | `--sref` | Image URL | Want to match the look and feel of another image? You can provide style reference! | | Omni Reference | `--oref` | Image URL | V7+. Reference a person or object from another image. In V8, replaces --cref and handles both person likeness and object form. **Removed in V8.1** | | Tile | `--tile` | No value | Use the tile parameter to create seamless tiled images for patterns and textures | | Version | `--version`, `--v` | 1-8.1 (current default: 7, latest: 8.1) | Use version parameter to explore and switch between different model versions | | HD Mode | `--hd` | No value | V8: native 2K resolution at 4x credit cost. V8.1: HD is the default — `--hd` is accepted but has no effect | | Draft | `--draft` | No value | Generate draft images using half GPU power in V7 and above for rapid prototyping | | Weird | `--weird`, `--w` | 0-3000 (default: 0) | Use the weird parameter to make your images strange and unconventional | | Fast | `--fast` | No value | Switch your GPU speed to fast mode (default processing speed) | | Image Weight | `--iw` | 0-3 (default: 1) | Control the influence of image prompts. Higher values make image prompts more influential | | Relax | `--relax` | No value | Switch your GPU speed to relax mode (slower but uses less quota) | | Turbo | `--turbo` | No value | Switch your GPU speed to turbo mode (4x faster, double cost, v5+ only) | | Niji | `--niji` | 5, 6 (current: 6) | Use our focused anime and East Asian aesthetic model | | Experimental | `--exp` | No value | Control the aesthetic effects of image generation with experimental features | | Motion | `--motion` | 1-4 (default: 2) | Control video motion status (only supports video tasks). Higher = more motion | ### Example Usage ``` A cute kitten --ar 16:9 --stylize 100 Beautiful landscape, sunset --quality 1 --chaos 50 Portrait --cref [reference image URL] --niji A small duck holding a magic wand --oref [object reference URL] Dynamic explosion --chaos 75 --weird 250 --s 200 Minimalist design --raw --stylize 0 --stop 80 Mountain scenery --ar 16:9 Abstract art --stylize 500 --weird 750 ``` ## Advanced Prompt Techniques ### Multi-Prompts Use double colons `::` to separate concepts and control their relative importance: ``` Hot dog:: animal --ar 16:9 Hot:: dog:: animal --ar 16:9 ``` The first example treats "Hot dog" as one concept, while the second separates "Hot" and "dog" as different concepts. ### Prompt Weights Add weights to multi-prompt sections using `::` followed by a number: ``` Beach::2 mountain forest --ar 16:9 ``` This gives "Beach" twice the weight of "mountain forest" in the generation. **Weight Examples:** - `::2` - Double weight - `::0.5` - Half weight - `::-0.5` - Negative weight (reduces influence) ### Negative Prompting Examples ``` Beautiful garden --no weeds, dead plants, brown leaves Portrait --no glasses, hat, beard Landscape --no buildings, cars, people ``` ### Advanced Parameter Combinations **Ultra-detailed realistic photo:** ``` Professional portrait --quality 2 --stylize 50 --chaos 10 ``` **Artistic and experimental:** ``` Abstract art --stylize 750 --weird 1500 --chaos 80 ``` **Character consistency across images:** ``` Character design --cref [URL] --seed 12345 --stylize 200 ``` **Anime style with motion:** ``` Dynamic action scene --niji 6 --motion 4 --chaos 30 ``` ## Supported Aspect Ratios Core aspect ratios and their typical applications: - **1:1** - Standard square, suitable for social media avatars, Instagram posts - **4:3** - Traditional rectangle, suitable for older monitors, tablets - **2:3** - Classic photography ratio, commonly used for frames, posters - **16:9** - Modern widescreen ratio, mainstream standard for HD video, smart TVs - **9:16** - Portrait ratio, optimized for mobile short videos, social media stories ### Setting Aspect Ratios You can quickly determine and set image aspect ratios through these methods: - **Based on pixel dimensions**: For 1920x1080 pixel images, input `--ar 1920:1080`, system automatically simplifies to `--ar 16:9` - **Based on physical dimensions**: For sizes like 8.5x11 inches, remove decimal points and input `--ar 85:110` - **Custom ratios**: Supports any integer ratios, such as `--ar 3:2` or `--ar 5:4` ### Important Notes - Default aspect ratio is 1:1, suitable for most basic scenarios - Only supports integer ratios, use 139:100 instead of 1.39:1 - Different model versions may have varying support for aspect ratios - Extreme aspect ratios (like 1:10 or 10:1) are experimental features with potentially unstable results - During HD processing, some aspect ratios may be fine-tuned for optimization ## Detailed Parameter Guidelines ### Stylize Parameter Effects **Low Stylize (0-50):** More literal interpretation of prompts - `--s 0`: Very literal, follows prompt closely - `--s 25`: Slight artistic interpretation - `--s 50`: Balanced between literal and artistic **Medium Stylize (100-250):** Default range with good artistic balance - `--s 100`: Default value, good balance - `--s 200`: More artistic interpretation - `--s 250`: Strong artistic styling **High Stylize (300-1000):** Heavy artistic interpretation - `--s 500`: Very artistic, may deviate from prompt - `--s 750`: Extremely artistic - `--s 1000`: Maximum artistic interpretation, minimal prompt adherence ### Chaos Parameter Effects **Low Chaos (0-25):** Consistent, predictable results - `--c 0`: Default, very consistent results - `--c 15`: Slight variation - `--c 25`: Moderate variation while staying on-theme **High Chaos (50-100):** Unpredictable, varied results - `--c 50`: Significant variation - `--c 75`: High variation, experimental - `--c 100`: Maximum chaos, very unpredictable results ### Quality Parameter Impact - `--q 0.25`: 4x faster, lower detail (draft quality) - `--q 0.5`: 2x faster, moderate detail - `--q 1`: Default quality and speed - `--q 2`: 2x slower, maximum detail (only v4+) ### Weird Parameter Effects **Subtle Weird (0-250):** Slight oddness - `--w 0`: Default, no weirdness - `--w 100`: Slightly unusual elements - `--w 250`: Noticeable strange elements **Strong Weird (500-1500):** Significant strangeness - `--w 750`: Very unusual and surreal - `--w 1500`: Extremely weird and abstract **Maximum Weird (2000-3000):** Extreme experimental results - `--w 2500`: Highly abstract and bizarre - `--w 3000`: Maximum weirdness, often unrecognizable ### Seed Parameter Usage Seeds are useful for: - **Consistency**: Same seed + prompt = similar results - **Variations**: Change other parameters while keeping seed - **Experimentation**: Test different prompts with same seed - **Reproducibility**: Share exact results with others **Important Notes:** - Seeds only work with same model version - Different aspect ratios may produce different results even with same seed - Seeds from older model versions won't work with newer versions ## Parameter Combination Suggestions - **High Quality Detailed Images**: `--quality 1 --stylize 250 --chaos 10` - **Creative Experimentation**: `--chaos 75 --stylize 50 --weird 500` - **Character Consistency**: `--cref [character image] --seed [fixed value] --chaos 0` - **Style Matching**: `--sref [style image] --stylize 100 --iw 1.5` - **Realistic Photography**: `--stylize 50 --quality 1 --raw` - **Abstract Art**: `--stylize 750 --weird 1000 --chaos 80` - **Anime/Manga Style**: `--niji 6 --stylize 200 --quality 1` - **Multiple Variations**: `--chaos 25 --stylize 150` ## Current Limitations The API currently does **not** support the following parameters for **image generation**: - `--repeat` parameter - `--bs`, `--batchsize` parameter (only supported in video functions with values [1,2,4]) - `--personalize` parameter - `{}` prompt variation syntax - `--stealth`/`--public` parameters - `--video` parameter (use video-specific endpoints instead) ## Object Reference (--oref) - V7 Update Object Reference allows you to reference an object from another image in your generation. ### Usage Add the `--oref` parameter at the end of your prompt, followed by your image URL. You can only use one image in object reference. **Example:** ``` A small duck holding a magic wand --oref http://image.png ``` ### Important Limitations (V7) - **Incompatible with V6.1 features**: Object reference is incompatible with features that still use V6.1 (such as inpainting or outpainting) - **Double GPU consumption**: Using object reference consumes 2x GPU time compared to regular V7 images - **Editing incompatibility**: Object reference images are currently incompatible with regional inpainting, pan, or outpaint. To edit these images, use the Edit interface and remove image references along with any `--oref` or `--ow` parameters - **Speed mode incompatibility**: Object reference is currently incompatible with speed modes or `--q 4` ## Important Usage Requirements - **When using enhance**: The original job must be created in draft mode with parameters `--v7 --draft` - **Draft mode**: Ultra-fast image prototyping (10x faster than normal mode) with slightly reduced quality but consuming only half the GPU resources. Use `--draft` parameter to activate. ## Supported Speed Modes Speed modes control the GPU type used for task execution, determining task execution time. The API provides **fast mode** and **turbo mode**, with **relax mode** currently not supported. ### Fast Mode (`--fast`) Fast mode is the default GPU speed mode where API requests are prioritized using GPU resources for processing. Usually completes image generation within 1 minute. - **Usage**: Activated with `--fast` parameter - **Default**: Used when no speed mode is specified - **Processing Time**: Typically under 1 minute for standard images ### Turbo Mode (`--turbo`) Turbo mode uses a high-performance GPU pool with processing speeds up to 4x faster than fast mode. This mode consumes double the GPU time quota and only supports v5 and above versions. - **Usage**: Activated with `--turbo` parameter - **Speed**: Up to 4x faster than fast mode - **Requirements**: Only supports v5+ versions - **Cost**: Consumes double GPU time quota - **Status**: Experimental feature - availability and billing may change ## Prompt Best Practices ### Effective Prompt Structure 1. **Subject**: What you want to see (e.g., "portrait of a woman") 2. **Style/Medium**: Art style or medium (e.g., "oil painting", "digital art") 3. **Details**: Specific details (e.g., "blue eyes, flowing hair") 4. **Environment**: Setting or background (e.g., "in a garden", "studio lighting") 5. **Parameters**: Add parameters at the end **Example:** ``` Portrait of an elderly wizard, oil painting style, long white beard, wise eyes, wearing purple robes, mystical library background --ar 2:3 --stylize 200 --quality 1 ``` ### Parameter Order Recommendations Place parameters in this order for best results: 1. Aspect ratio (`--ar`) 2. Quality (`--quality`) 3. Stylize (`--stylize`) 4. Chaos (`--chaos`) 5. Weird (`--weird`) 6. Speed mode (`--fast`, `--turbo`) 7. Model version (`--v`, `--niji`) 8. Special modes (`--raw`, `--tile`, `--draft`) ### Common Mistakes to Avoid - **Too many conflicting parameters**: Keep combinations logical - **Extreme parameter values**: Start with moderate values and adjust - **Inconsistent aspect ratios**: Choose ratios that match your intended use - **Overuse of chaos**: High chaos can make results unpredictable - **Wrong model versions**: Use appropriate version for your style needs --- # Video Parameters _Video generation parameters reference_ ## Video Parameter List | Parameter | Values | Description | |--------------------------|---------------------------|--------------------------------------------------------------------------------| | Motion | `low`, `high` | **Low motion**: Static scenes/subtle movements (default) `--motion low`
**High motion**: Large camera movements (may produce artistic effects) `--motion high` | | Raw | - | Use `--raw` parameter to reduce automatic system enhancements for more precise control | | End Frame | `image url` | Use `--end [image url]` to specify the final frame of the video | | Loop | - | Use `--loop` parameter to generate videos where the first and last frames are identical | | Batch Size | `1`, `2`, `4` | Use `--bs [1\|2\|4]` parameter to control the number of videos generated per task | ## Example Usage ``` Create a video with high motion --motion high Generate a looping video with specific end frame --loop --end https://example.com/end-frame.jpg Create multiple videos with raw mode --bs 4 --raw Combine parameters for precise control --motion low --loop --bs 2 ``` ## Motion Mode Options ### Low Motion Mode (`--motion low`) - Default Setting **Characteristics:** - Static scenes with gentle camera movements - Subtle character actions and minimal motion - Smooth and stable visual effects **Suitable Scenarios:** - Cinematic atmosphere creation - Mood setting scenes - Content requiring stable visual effects **Effect Examples:** - Slow camera pans - Fade in/out transitions - Subtle facial expression changes ### High Motion Mode (`--motion high`) **Characteristics:** - Large camera movements and rapid action changes - Strong visual impact and dynamic effects - More dramatic motion sequences **Suitable Scenarios:** - Action scenes and dynamic content - Transition effects - Content requiring emphasized movement **Important Notes:** - May cause unnatural actions or visual anomalies - Potential issues include stuttering or visual glitches - Use with caution for professional content ## Parameter Combination Suggestions - **Subtle Animation**: `--motion low --loop` - **Dynamic Scenes**: `--motion high --bs 2` - **Precise Control**: `--raw --motion low` - **Custom Story Arc**: `--end [image url] --motion high` --- # Output Storage _Image storage duration and operation validity periods_ ## Storage Duration Images generated are stored for 30 days after creation and automatically deleted thereafter. Please ensure you save your images to permanent storage before the expiration period. ## Operation Validity Operations on generated images (e.g., upscaling, variations) are valid for 3 days post-creation. --- # Text to Image _Generate images from text prompts_ **Endpoint:** `POST /v1/diffusion` ## Headers | Header | Type | Required | Description | |--------|------|----------|-------------| | `x-api-key` | string | Yes | Your API key | ## Request Body | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `text` | string | Yes | Text prompt for image generation (1-8192 characters) | | `callback` | string | No | Callback URL for task completion notifications | ## Example Request ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/diffusion" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "A beautiful sunset over the snow mountains --v 7 --draft", "callback": "https://webhook.site/d0ca59bc-35a6-4a1e-b1b1-aea7faeb7f67" }' ``` ```python Python import requests url = "https://api.legnext.ai/api/v1/diffusion" headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } data = { "text": "A beautiful sunset over the snow mountains --v 7 --draft", "callback": "https://webhook.site/d0ca59bc-35a6-4a1e-b1b1-aea7faeb7f67" } response = requests.post(url, headers=headers, json=data) result = response.json() print(result) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/diffusion', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ text: 'A beautiful sunset over the snow mountains --v 7 --draft', callback: 'https://webhook.site/d0ca59bc-35a6-4a1e-b1b1-aea7faeb7f67' }) }); const result = await response.json(); console.log(result); ``` ## Response Returns a task object with status "pending". The task will be processed asynchronously. ```json { "job_id": "789320d3-4b20-46d3-a804-6165a079176a", "model": "midjourney", "task_type": "diffusion", "status": "pending", "config": { "service_mode": "public", "webhook_config": { "endpoint": "", "secret": "" } }, "input": null, "output": { "image_url": "", "image_urls": null, "seed": "" }, "meta": { "created_at": "2025-12-17T11:08:36Z", "started_at": "0001-01-01T00:00:00Z", "ended_at": "0001-01-01T00:00:00Z", "usage": { "type": "point", "frozen": 80, "consume": 0 } }, "detail": null, "logs": [], "error": { "code": 0, "raw_message": "", "message": "", "detail": null } } ``` > **Note:** Use the `job_id` to [check task status](https://docs.legnext.ai/api-reference/task-management/get-task) and retrieve the generated images when the task is completed. --- # Variation _Create variations of existing images_ **Endpoint:** `POST /v1/variation` ## Headers | Header | Type | Required | Description | |--------|------|----------|-------------| | `x-api-key` | string | Yes | Your API key | ## Request Body | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `jobId` | string | Yes | ID of the original image generation task | | `imageNo` | integer | Yes | Image number to vary (0/1/2/3) | | `type` | integer | Yes | Variation intensity type (0 or 1) | | `remixPrompt` | string | No | Additional prompt for guided variation (1-8192 characters) | | `callback` | string | No | Callback URL for task completion notifications | ## Variation Types | Type | Name | Description | |------|------|-------------| | 0 | Subtle | Minor changes while preserving most original elements | | 1 | Strong | More dramatic variations with significant changes | ## Example Requests ### Subtle Variation ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/variation" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "jobId": "5dd94ec3-7282-4f04-9445-59e850ef1822", "imageNo": 0, "type": 0, "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" }' ``` ```python Python import requests url = "https://api.legnext.ai/api/v1/variation" headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } data = { "jobId": "5dd94ec3-7282-4f04-9445-59e850ef1822", "imageNo": 0, "type": 0, "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" } response = requests.post(url, headers=headers, json=data) result = response.json() print(result) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/variation', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ jobId: '5dd94ec3-7282-4f04-9445-59e850ef1822', imageNo: 0, type: 0, callback: 'https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d' }) }); const result = await response.json(); console.log(result); ``` ## Response Returns a task object containing the task information. ```json { "job_id": "340721c6-86eb-4620-ba38-8df46fb507b6", "model": "midjourney", "task_type": "variation", "status": "pending", "config": { "service_mode": "public", "webhook_config": { "endpoint": "https://webhook.site/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "secret": "" } }, "input": null, "output": { "image_url": "", "image_urls": null, "seed": "" }, "meta": { "created_at": "", "started_at": "", "ended_at": "", "usage": { "type": "point", "frozen": 120, "consume": 0 } }, "detail": null, "logs": [], "error": { "code": 0, "raw_message": "", "message": "", "detail": null } } ``` > **Note:** This is the initial success response. Use the `job_id` to check the task status via the [Get Task](https://docs.legnext.ai/api-reference/task-management/get-task) endpoint to retrieve the completed result with image URLs. --- # Upscale _Enhance image resolution and quality_ **Endpoint:** `POST /v1/upscale` ## Headers | Header | Type | Required | Description | |--------|------|----------|-------------| | `x-api-key` | string | Yes | Your API key | ## Request Body | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `jobId` | string | Yes | ID of the original image generation task | | `imageNo` | integer | Yes | Image number to upscale (0/1/2/3) | | `type` | integer | Yes | Upscaling type (0 or 1) | | `callback` | string | No | Callback URL for task completion notifications | ## Upscale Types | Type | Name | Description | Supported Models | |------|------|-------------|------------------| | 0 | Subtle | Conservative enhancement preserving original details | v6, niji6, v6.1, v7 | | 1 | Creative | More aggressive enhancement with artistic interpretation | v6, niji6, v6.1, v7 | | 2 | 2x | 2x resolution increase (deprecated) | v5, niji5 | | 3 | 4x | 4x resolution increase (deprecated) | v5, niji5 | ## Example Requests ### Subtle Upscale ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/upscale" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "jobId": "5dd94ec3-7282-4f04-9445-59e850ef1822", "imageNo": 0, "type": 0, "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" }' ``` ```python Python import requests url = "https://api.legnext.ai/api/v1/upscale" headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } data = { "jobId": "5dd94ec3-7282-4f04-9445-59e850ef1822", "imageNo": 0, "type": 0, "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" } response = requests.post(url, headers=headers, json=data) result = response.json() print(result) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/upscale', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ jobId: '5dd94ec3-7282-4f04-9445-59e850ef1822', imageNo: 0, type: 0, callback: 'https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d' }) }); const result = await response.json(); console.log(result); ``` ### Creative Upscale ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/upscale" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "jobId": "5dd94ec3-7282-4f04-9445-59e850ef1822", "imageNo": 0, "type": 1, "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" }' ``` ```python Python import requests url = "https://api.legnext.ai/api/v1/upscale" headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } data = { "jobId": "5dd94ec3-7282-4f04-9445-59e850ef1822", "imageNo": 0, "type": 1, "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" } response = requests.post(url, headers=headers, json=data) result = response.json() print(result) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/upscale', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ jobId: '5dd94ec3-7282-4f04-9445-59e850ef1822', imageNo: 0, type: 1, callback: 'https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d' }) }); const result = await response.json(); console.log(result); ``` ## Response Returns a task object containing the task information. ```json { "job_id": "8541c46c-6af7-49a5-a5a2-dd82eae7e6c8", "model": "midjourney", "task_type": "upscale", "status": "pending", "config": { "service_mode": "public", "webhook_config": { "endpoint": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d", "secret": "" } }, "input": null, "output": { "image_url": "", "image_urls": null, "seed": "" }, "meta": { "created_at": "", "started_at": "", "ended_at": "", "usage": { "type": "point", "frozen": 120, "consume": 0 } }, "detail": null, "logs": [], "error": { "code": 0, "raw_message": "", "message": "", "detail": null } } ``` > **Note:** This is the initial success response. Use the `job_id` to check the task status via the [Get Task](https://docs.legnext.ai/api-reference/task-management/get-task) endpoint to retrieve the completed result with image URLs. ## Upscale Types Comparison ### Subtle (Type 0) - **Best For**: Photography, realistic images, preserving original details - **Characteristics**: - Minimal artistic interpretation - Preserves original composition and style - Clean, sharp enhancement - Suitable for professional use ### Creative (Type 1) - **Best For**: Artistic images, illustrations, creative projects - **Characteristics**: - Enhanced artistic details - More dramatic improvement - May add creative interpretation - Good for artistic workflows --- # Reroll _Re-execute tasks with same parameters_ **Endpoint:** `POST /v1/reroll` ## Headers | Header | Type | Required | Description | |--------|------|----------|-------------| | `x-api-key` | string | Yes | Your API key | ## Request Body | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `jobId` | string | Yes | ID of the original task to reroll | | `callback` | string | No | Callback URL for task completion notifications | ## Example Request ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/reroll" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "jobId": "5dd94ec3-7282-4f04-9445-59e850ef1822", "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" }' ``` ```python Python import requests url = "https://api.legnext.ai/api/v1/reroll" headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } data = { "jobId": "5dd94ec3-7282-4f04-9445-59e850ef1822", "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" } response = requests.post(url, headers=headers, json=data) result = response.json() print(result) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/reroll', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ jobId: '5dd94ec3-7282-4f04-9445-59e850ef1822', callback: 'https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d' }) }); const result = await response.json(); console.log(result); ``` ## Response Returns a task object containing the task information. ```json { "job_id": "b54ab480-be6e-470e-8eab-5af763a4f6e0", "model": "midjourney", "task_type": "reroll", "status": "pending", "config": { "service_mode": "public", "webhook_config": { "endpoint": "https://webhook.site/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "secret": "" } }, "input": null, "output": { "image_url": "", "image_urls": null, "seed": "" }, "meta": { "created_at": "", "started_at": "", "ended_at": "", "usage": { "type": "point", "frozen": 80, "consume": 0 } }, "detail": null, "logs": [], "error": { "code": 0, "raw_message": "", "message": "", "detail": null } } ``` > **Note:** This is the initial success response. Use the `job_id` to check the task status via the [Get Task](https://docs.legnext.ai/api-reference/task-management/get-task) endpoint to retrieve the completed result with image URLs. --- # Blend _Seamlessly combine 2-5 images into a single unique creation with AI-powered blending technology_ **Endpoint:** `POST /v1/blend` Turn multiple photos into a single unique creation using /blend ## Headers | Header | Type | Required | Description | |--------|------|----------|-------------| | `x-api-key` | string | Yes | Your API key | ## Request Body | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `imgUrls` | string[] | Yes | Array of 2-5 images to blend | | `aspect_ratio` | string | Yes | Aspect ratio: `2:3`, `1:1`, or `3:2`.| | `callback` | string | No | Callback URL for task completion notifications | ## Example Request ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/blend" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "imgUrls": [ "https://example.com/image1.png", "https://example.com/image2.png" ], "aspect_ratio": "1:1", "callback": "https://webhook.site/your-webhook-id" }' ``` ```python Python import requests url = "https://api.legnext.ai/api/v1/blend" headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } data = { "imgUrls": [ "https://example.com/image1.png", "https://example.com/image2.png" ], "aspect_ratio": "1:1", "callback": "https://webhook.site/your-webhook-id" } response = requests.post(url, headers=headers, json=data) result = response.json() print(result) # Query result job_id = result["job_id"] query_url = f"https://api.legnext.ai/api/v1/job/{job_id}" result = requests.get(query_url, headers={"x-api-key": "YOUR_API_KEY"}) output = result.json()["output"] print("Blended image:", output["image_url"]) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/blend', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ imgUrls: [ 'https://example.com/image1.png', 'https://example.com/image2.png' ], aspect_ratio: '1:1', callback: 'https://webhook.site/your-webhook-id' }) }); const result = await response.json(); console.log(result); // Poll for result const jobId = result.job_id; let output; while (true) { const queryResponse = await fetch( `https://api.legnext.ai/api/v1/job/${jobId}`, { headers: { 'x-api-key': 'YOUR_API_KEY' } } ); const data = await queryResponse.json(); if (data.status === 'completed') { output = data.output; break; } await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5 seconds } console.log('Blended image:', output.image_url); ``` ## Response Returns a task object containing the task information. ```json { "job_id": "ea1aff8a-9c68-47b8-9693-9b10570a1910", "model": "midjourney", "task_type": "blend", "status": "pending", "config": { "service_mode": "public", "webhook_config": { "endpoint": "https://webhook.site/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "secret": "" } }, "input": null, "output": { "image_url": "", "image_urls": null, "seed": "" }, "meta": { "created_at": "", "started_at": "", "ended_at": "", "usage": { "type": "point", "frozen": 80, "consume": 0 } }, "detail": null, "logs": [], "error": { "code": 0, "raw_message": "", "message": "", "detail": null } } ``` > **Note:** This is the initial success response. Use the `job_id` to check the task status via the [Get Task](https://docs.legnext.ai/api-reference/task-management/get-task) endpoint to retrieve the completed result with image URLs. --- # Describe _Generate text descriptions from images_ **Endpoint:** `POST /v1/describe` ## Headers | Header | Type | Required | Description | |--------|------|----------|-------------| | `x-api-key` | string | Yes | Your API key | ## Request Body | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `imgUrl` | string | yes | URL link to the image | | `callback` | string | No | Callback URL for task completion notifications | ## Example Request ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/describe" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "imgUrl": "https://example.com/image.png", "callback": "https://webhook.site/your-webhook-id" }' ``` ```python Python import requests url = "https://api.legnext.ai/api/v1/describe" headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } data = { "imgUrl": "https://example.com/image.png", "callback": "https://webhook.site/your-webhook-id" } response = requests.post(url, headers=headers, json=data) result = response.json() print(result) # Query result job_id = result["job_id"] query_url = f"https://api.legnext.ai/api/v1/job/{job_id}" result = requests.get(query_url, headers={"x-api-key": "YOUR_API_KEY"}) output = result.json()["output"] print("Description:", output["description"]) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/describe', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ imgUrl: 'https://example.com/image.png', callback: 'https://webhook.site/your-webhook-id' }) }); const result = await response.json(); console.log(result); // Poll for result const jobId = result.job_id; let output; while (true) { const queryResponse = await fetch( `https://api.legnext.ai/api/v1/job/${jobId}`, { headers: { 'x-api-key': 'YOUR_API_KEY' } } ); const data = await queryResponse.json(); if (data.status === 'completed') { output = data.output; break; } await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5 seconds } console.log('Description:', output.description); ``` ## Response Returns a task object containing the task information. ```json { "job_id": "54aeca4b-f443-41f3-8b94-28cbdc2e7e20", "model": "midjourney", "task_type": "describe", "status": "pending", "config": { "service_mode": "public", "webhook_config": { "endpoint": "", "secret": "" } }, "input": null, "output": { "promptEn": "", "description": "", "finalPrompt": "", "prompts": [] }, "meta": { "created_at": "", "started_at": "", "ended_at": "", "usage": { "type": "point", "frozen": 20, "consume": 0 } }, "detail": null, "logs": [], "error": { "code": 0, "raw_message": "", "message": "", "detail": null } } ``` > **Note:** This is the initial success response. Use the `job_id` to check the task status via the [Get Task](https://docs.legnext.ai/api-reference/task-management/get-task) endpoint to retrieve the completed result with prompt descriptions. --- # Shorten _Simplify prompts to essential elements_ **Endpoint:** `POST /v1/shorten` ## Headers | Header | Type | Required | Description | |--------|------|----------|-------------| | `x-api-key` | string | Yes | Your API key | ## Request Body | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `prompt` | string | Yes | The prompt to analyze and shorten (1-8192 characters) | | `callback` | string | No | Callback URL for task completion notifications | ## Example Request ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/shorten" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "prompt": "A cyberpunk hacker workspace filled with holographic screens, glowing code streams, mechanical keyboards, neon reflections, cables and circuit boards everywhere, volumetric lighting, ultra-detailed sci-fi aesthetic, cinematic atmosphere, inspired by Ghost in the Shell and Blade Runner, rendered in octane, 8k resolution --ar 21:9 --v 7 --style raw --q 2", "callback": "https://webhook.site/your-webhook-id" }' ``` ```python Python import requests url = "https://api.legnext.ai/api/v1/shorten" headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } data = { "prompt": "A cyberpunk hacker workspace filled with holographic screens, glowing code streams, mechanical keyboards, neon reflections, cables and circuit boards everywhere, volumetric lighting, ultra-detailed sci-fi aesthetic, cinematic atmosphere, inspired by Ghost in the Shell and Blade Runner, rendered in octane, 8k resolution --ar 21:9 --v 7 --style raw --q 2", "callback": "https://webhook.site/your-webhook-id" } response = requests.post(url, headers=headers, json=data) result = response.json() print(result) # Query result job_id = result["job_id"] query_url = f"https://api.legnext.ai/api/v1/job/{job_id}" result = requests.get(query_url, headers={"x-api-key": "YOUR_API_KEY"}) output = result.json()["output"] print("Shortened prompts:", output["prompts"]) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/shorten', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt: 'A cyberpunk hacker workspace filled with holographic screens, glowing code streams, mechanical keyboards, neon reflections, cables and circuit boards everywhere, volumetric lighting, ultra-detailed sci-fi aesthetic, cinematic atmosphere, inspired by Ghost in the Shell and Blade Runner, rendered in octane, 8k resolution --ar 21:9 --v 7 --style raw --q 2', callback: 'https://webhook.site/your-webhook-id' }) }); const result = await response.json(); console.log(result); // Poll for result const jobId = result.job_id; let output; while (true) { const queryResponse = await fetch( `https://api.legnext.ai/api/v1/job/${jobId}`, { headers: { 'x-api-key': 'YOUR_API_KEY' } } ); const data = await queryResponse.json(); if (data.status === 'completed') { output = data.output; break; } await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5 seconds } console.log('Shortened prompts:', output.prompts); ``` ## Response Returns a task object containing the task information. ```json { "job_id": "48833d7a-d588-4ad9-897b-25e1ea9edff7", "model": "midjourney", "task_type": "shorten", "status": "pending", "config": { "service_mode": "public", "webhook_config": { "endpoint": "", "secret": "" } }, "input": null, "output": { "promptEn": "", "description": "", "finalPrompt": "", "prompts": [] }, "meta": { "created_at": "", "started_at": "", "ended_at": "", "usage": { "type": "point", "frozen": 20, "consume": 0 } }, "detail": null, "logs": [], "error": { "code": 0, "raw_message": "", "message": "", "detail": null } } ``` > **Note:** This is the initial success response. Use the `job_id` to check the task status via the [Get Task](https://docs.legnext.ai/api-reference/task-management/get-task) endpoint to retrieve the completed result with shortened prompts. --- # Pan _Extend images in specified direction_ **Endpoint:** `POST /v1/pan` ## Headers | Header | Type | Required | Description | |--------|------|----------|-------------| | `x-api-key` | string | Yes | Your API key | ## Request Body | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `jobId` | string | Yes | ID of the original image generation task | | `imageNo` | integer | Yes | Image number to extend (0/1/2/3) | | `direction` | integer | Yes | Extension direction (0-3) | | `scale` | float | Yes | Extension scale ratio (1.1-3.0) | | `remixPrompt` | string | No | Text prompt for the extended area (1-8192 characters) | | `callback` | string | No | Callback URL for task completion notifications | ## Direction Values | Value | Direction | |-------|-----------| | 0 | Down | | 1 | Right | | 2 | Up | | 3 | Left | ## Scale Parameter The `scale` parameter defines the ratio of the new image area to the original in the extension direction: - **Range**: 1.1 to 3.0 - **Example**: For a 1:1 aspect ratio image extending right by 13%: - `scale = 1.13` means the final image will be 13% wider in the specified direction ## Example Requests ### Extend Right ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/pan" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "jobId": "5dd94ec3-7282-4f04-9445-59e850ef1822", "imageNo": 0, "direction": 1, "scale": 1.5, "remixPrompt": "a lake near the mountain", "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" }' ``` ```python Python import requests url = "https://api.legnext.ai/api/v1/pan" headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } data = { "jobId": "5dd94ec3-7282-4f04-9445-59e850ef1822", "imageNo": 0, "direction": 1, "scale": 1.5, "remixPrompt": "a lake near the mountain", "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" } response = requests.post(url, headers=headers, json=data) result = response.json() print(result) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/pan', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ jobId: '5dd94ec3-7282-4f04-9445-59e850ef1822', imageNo: 0, direction: 1, scale: 1.5, remixPrompt: 'a lake near the mountain', callback: 'https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d' }) }); const result = await response.json(); console.log(result); ``` ## Response Returns a task object containing the task information. ```json { "job_id": "d0caddaa-028b-4074-985e-7894b2aef5a0", "model": "midjourney", "task_type": "pan", "status": "pending", "config": { "service_mode": "public", "webhook_config": { "endpoint": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d", "secret": "" } }, "input": null, "output": { "image_url": "", "image_urls": null, "seed": "" }, "meta": { "created_at": "", "started_at": "", "ended_at": "", "usage": { "type": "point", "frozen": 80, "consume": 0 } }, "detail": null, "logs": [], "error": { "code": 0, "raw_message": "", "message": "", "detail": null } } ``` > **Note:** This is the initial success response. Use the `job_id` to check the task status via the [Get Task](https://docs.legnext.ai/api-reference/task-management/get-task) endpoint to retrieve the completed result with image URLs. ## Technical Notes - Extends in only one specified direction (unlike outpaint which extends in all directions) - Scale parameter determines extension ratio (1.1-3.0) - AI maintains visual continuity with the original image - Use descriptive prompts to guide the content of the extended area --- # Outpaint _Expand images in all directions_ **Endpoint:** `POST /v1/outpaint` ## Headers | Header | Type | Required | Description | |--------|------|----------|-------------| | `x-api-key` | string | Yes | Your API key | ## Request Body | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `jobId` | string | Yes | ID of the original image generation task | | `imageNo` | integer | Yes | Image number to extend (0/1/2/3) | | `scale` | float | Yes | Extension scale ratio (1.1-2.0) | | `remixPrompt` | string | No | Text prompt for the extended areas (1-8192 characters) | | `callback` | string | No | Callback URL for task completion notifications | ## Parameters Detail ### Scale Parameter The `scale` parameter defines how much larger the final image will be compared to the original: - **Range**: 1.1 to 2.0 - **Example**: For a 1:1 aspect ratio image: - `scale = 1.2` means the original image will occupy 83% of the new image (20% extension) - `scale = 2.0` means the original image will occupy 50% of the new image (100% extension) ## Example Request ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/outpaint" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "jobId": "5dd94ec3-7282-4f04-9445-59e850ef1822", "imageNo": 0, "scale": 1.5, "remixPrompt": "clouds over the sky", "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" }' ``` ```python Python import requests url = "https://api.legnext.ai/api/v1/outpaint" headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } data = { "jobId": "5dd94ec3-7282-4f04-9445-59e850ef1822", "imageNo": 0, "scale": 1.5, "remixPrompt": "clouds over the sky", "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" } response = requests.post(url, headers=headers, json=data) result = response.json() print(result) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/outpaint', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ jobId: '5dd94ec3-7282-4f04-9445-59e850ef1822', imageNo: 0, scale: 1.5, remixPrompt: 'clouds over the sky', callback: 'https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d' }) }); const result = await response.json(); console.log(result); ``` ## Response Returns a task object containing the task information. ```json { "job_id": "c4e210ca-6cf1-4453-a204-00f26a8e75cc", "model": "midjourney", "task_type": "outpaint", "status": "pending", "config": { "service_mode": "public", "webhook_config": { "endpoint": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d", "secret": "" } }, "input": null, "output": { "image_url": "", "image_urls": null, "seed": "" }, "meta": { "created_at": "", "started_at": "", "ended_at": "", "usage": { "type": "point", "frozen": 80, "consume": 0 } }, "detail": null, "logs": [], "error": { "code": 0, "raw_message": "", "message": "", "detail": null } } ``` > **Note:** This is the initial success response. Use the `job_id` to check the task status via the [Get Task](https://docs.legnext.ai/api-reference/task-management/get-task) endpoint to retrieve the completed result with image URLs. --- # Inpaint _Edit specific regions with masks_ **Endpoint:** `POST /v1/inpaint` ## Headers | Header | Type | Required | Description | |--------|------|----------|-------------| | `x-api-key` | string | Yes | Your API key | ## Request Body | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `jobId` | string | Yes | ID of the original image generation task | | `imageNo` | integer | Yes | Image number to edit (0/1/2/3) | | `mask` | [Mask](#mask) | Yes | Regions to repaint | | `remixPrompt` | string | No | Text prompt for the repaint area (1-8192 characters) | | `area` | [Polygon](#polygon) | No | Single polygon area to repaint (deprecated, use mask instead) | | `callback` | string | No | Callback URL for task completion notifications | ## Data Types ### Mask Choose one of the following methods to define the repaint area: | Field | Type | Description | |-------|------|-------------| | `areas` | [Polygon](#polygon)[] | Array of polygonal areas to repaint | | `url` | string | Black and white mask image URL (white areas will be repainted) | ### Polygon | Field | Type | Description | |-------|------|-------------| | `width` | integer | Image width in pixels (500-4096) | | `height` | integer | Image height in pixels (500-4096) | | `points` | integer[] | Polygon coordinates in XYXY format, clockwise from top-left | ## Example Request ### Using Polygon Areas ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/inpaint" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "jobId": "5dd94ec3-7282-4f04-9445-59e850ef1822", "imageNo": 0, "mask": { "areas": [ { "width": 500, "height": 500, "points": [ 10, 10, 10, 100, 100, 100, 100, 10 ] } ] }, "remixPrompt": "Add a tree in the center", "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" }' ``` ```python Python import requests url = "https://api.legnext.ai/api/v1/inpaint" headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } data = { "jobId": "5dd94ec3-7282-4f04-9445-59e850ef1822", "imageNo": 0, "mask": { "areas": [ { "width": 500, "height": 500, "points": [ 10, 10, 10, 100, 100, 100, 100, 10 ] } ] }, "remixPrompt": "Add a tree in the center", "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" } response = requests.post(url, headers=headers, json=data) result = response.json() print(result) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/inpaint', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ jobId: '5dd94ec3-7282-4f04-9445-59e850ef1822', imageNo: 0, mask: { areas: [ { width: 500, height: 500, points: [ 10, 10, 10, 100, 100, 100, 100, 10 ] } ] }, remixPrompt: 'Add a tree in the center', callback: 'https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d' }) }); const result = await response.json(); console.log(result); ``` ### Using Mask Image ```json { "jobId": "job_12345", "imageNo": 0, "remixPrompt": "Add autumn leaves", "mask": { "url": "https://example.com/mask-image.png" }, "callback": "https://your-domain.com/webhook" } ``` ## Response Returns a task object containing the task information. ```json { "job_id": "72e20f1a-6c76-4ec5-bda2-490016056fa8", "model": "midjourney", "task_type": "inpaint", "status": "pending", "config": { "service_mode": "public", "webhook_config": { "endpoint": "https://webhook.site/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "secret": "" } }, "input": null, "output": { "image_url": "", "image_urls": null, "seed": "" }, "meta": { "created_at": "", "started_at": "", "ended_at": "", "usage": { "type": "point", "frozen": 120, "consume": 0 } }, "detail": null, "logs": [], "error": { "code": 0, "raw_message": "", "message": "", "detail": null } } ``` > **Note:** This is the initial success response. Use the `job_id` to check the task status via the [Get Task](https://docs.legnext.ai/api-reference/task-management/get-task) endpoint to retrieve the completed result with image URLs. --- # Remix _Transform images with new prompts_ **Endpoint:** `POST /v1/remix` ## Headers | Header | Type | Required | Description | |--------|------|----------|-------------| | `x-api-key` | string | Yes | Your API key | ## Request Body | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `jobId` | string | Yes | ID of the original image generation task | | `imageNo` | integer | Yes | Image number to remix (0/1/2/3) | | `remixPrompt` | string | Yes | New text prompt for transformation (1-8192 characters) | | `mode` | integer | No | Remix intensity mode (0 or 1, default: 0) | | `callback` | string | No | Callback URL for task completion notifications | ## Remix Modes | Mode | Type | Description | |------|------|-------------| | 0 | Strong | Dramatic transformation with significant changes | | 1 | Subtle | Minor adjustments while preserving most original elements | ## Example Requests ### Strong Remix ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/remix" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "jobId": "5dd94ec3-7282-4f04-9445-59e850ef1822", "imageNo": 0, "mode": 0, "remixPrompt": "Change style to watercolor painting", "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" }' ``` ```python Python import requests url = "https://api.legnext.ai/api/v1/remix" headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } data = { "jobId": "5dd94ec3-7282-4f04-9445-59e850ef1822", "imageNo": 0, "mode": 0, "remixPrompt": "Change style to watercolor painting", "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" } response = requests.post(url, headers=headers, json=data) result = response.json() print(result) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/remix', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ jobId: '5dd94ec3-7282-4f04-9445-59e850ef1822', imageNo: 0, mode: 0, remixPrompt: 'Change style to watercolor painting', callback: 'https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d' }) }); const result = await response.json(); console.log(result); ``` ### Subtle Remix ```json { "jobId": "5dd94ec3-7282-4f04-9445-59e850ef1822", "imageNo": 0, "remixPrompt": "Change the time of day to golden hour sunset", "mode": 1, "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" } ``` ## Response Returns a task object containing the task information. ```json { "job_id": "9e0f9ff3-abea-498e-a44a-157e10b28e93", "model": "midjourney", "task_type": "remix", "status": "pending", "config": { "service_mode": "public", "webhook_config": { "endpoint": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d", "secret": "" } }, "input": null, "output": { "image_url": "", "image_urls": null, "seed": "" }, "meta": { "created_at": "", "started_at": "", "ended_at": "", "usage": { "type": "point", "frozen": 120, "consume": 0 } }, "detail": null, "logs": [], "error": { "code": 0, "raw_message": "", "message": "", "detail": null } } ``` > **Note:** This is the initial success response. Use the `job_id` to check the task status via the [Get Task](https://docs.legnext.ai/api-reference/task-management/get-task) endpoint to retrieve the completed result with image URLs. --- # Edit _Edit and repaint image areas_ **Endpoint:** `POST /v1/edit` ## Headers | Header | Type | Required | Description | |--------|------|----------|-------------| | `x-api-key` | string | Yes | Your API key | ## Request Body | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `jobId` | string | Yes | ID of the original image generation task | | `imageNo` | integer | Yes | Image number to edit (0/1/2/3) | | `canvas` | [Canvas](#canvas) | Yes | Target canvas dimensions | | `imgPos` | [CanvasImg](#canvasimg) | Yes | Image position relative to canvas | | `remixPrompt` | string | Yes | Text prompt for the edit | | `mask` | [Mask](#mask) | No | Areas to repaint on the original image | | `callback` | string | No | Callback URL for task completion notifications | ## Data Types ### Canvas | Field | Type | Description | |-------|------|-------------| | `width` | integer | Canvas width in pixels | | `height` | integer | Canvas height in pixels | ### CanvasImg | Field | Type | Description | |-------|------|-------------| | `width` | integer | Image width in pixels | | `height` | integer | Image height in pixels | | `x` | integer | Horizontal offset from canvas top-left | | `y` | integer | Vertical offset from canvas top-left | ### Mask | Field | Type | Description | |-------|------|-------------| | `areas` | [Polygon](#polygon)[] | Polygonal areas to repaint (optional) | | `url` | string | Black and white mask image URL (optional) | ### Polygon | Field | Type | Description | |-------|------|-------------| | `width` | integer | Image width in pixels (500-4096) | | `height` | integer | Image height in pixels (500-4096) | | `points` | integer[] | Polygon coordinates in XYXY format, clockwise from top-left | ## Example Request ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/edit" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "jobId": "c6821434-5e41-408f-b42b-2562306b109c", "imageNo": 1, "canvas": { "width": 1024, "height": 1024 }, "imgPos": { "width": 512, "height": 512, "x": 256, "y": 256 }, "remixPrompt": "A beautiful landscape with mountains", "mask": { "areas": [ { "width": 500, "height": 500, "points": [10, 10, 10, 100, 100, 100, 100, 10] } ] } }' ``` ```python Python import requests url = "https://api.legnext.ai/api/v1/edit" headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } data = { "jobId": "c6821434-5e41-408f-b42b-2562306b109c", "imageNo": 1, "canvas": { "width": 1024, "height": 1024 }, "imgPos": { "width": 512, "height": 512, "x": 256, "y": 256 }, "remixPrompt": "A beautiful landscape with mountains", "mask": { "areas": [ { "width": 500, "height": 500, "points": [10, 10, 10, 100, 100, 100, 100, 10] } ] } } response = requests.post(url, headers=headers, json=data) result = response.json() print(result) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/edit', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ jobId: 'c6821434-5e41-408f-b42b-2562306b109c', imageNo: 1, canvas: { width: 1024, height: 1024 }, imgPos: { width: 512, height: 512, x: 256, y: 256 }, remixPrompt: 'A beautiful landscape with mountains', mask: { areas: [ { width: 500, height: 500, points: [10, 10, 10, 100, 100, 100, 100, 10] } ] } }) }); const result = await response.json(); console.log(result); ``` ## Response Returns a task object containing the task information. ```json { "job_id": "4017934e-35dd-4640-9585-68c224a66f3b", "model": "midjourney", "task_type": "edit", "status": "pending", "config": { "service_mode": "public", "webhook_config": { "endpoint": "", "secret": "" } }, "input": null, "output": { "image_url": "", "image_urls": null, "seed": "" }, "meta": { "created_at": "", "started_at": "", "ended_at": "", "usage": { "type": "point", "frozen": 120, "consume": 0 } }, "detail": null, "logs": [], "error": { "code": 0, "raw_message": "", "message": "", "detail": null } } ``` > **Note:** This is the initial success response. Use the `job_id` to check the task status via the [Get Task](https://docs.legnext.ai/api-reference/task-management/get-task) endpoint to retrieve the completed result with image URLs. --- # Upload paint _Advanced editing with custom uploads_ **Endpoint:** `POST /v1/upload-paint` ## Headers | Header | Type | Required | Description | |--------|------|----------|-------------| | `x-api-key` | string | Yes | Your API key | ## Request Body | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `imgUrl` | string | Yes | URL of the source image (max length: 1024 characters) | | `canvas` | [Canvas](#canvas) | Yes | Target canvas dimensions | | `imgPos` | [CanvasImg](#canvasimg) | Yes | Image position and size on canvas | | `remixPrompt` | string | Yes | Text prompt for the editing operation | | `mask` | [Mask](#mask) | Yes | Areas to edit on the original image | | `callback` | string | No | Callback URL for task completion notifications | ## Data Types ### Canvas | Field | Type | Description | |-------|------|-------------| | `width` | integer | Canvas width in pixels | | `height` | integer | Canvas height in pixels | ### CanvasImg | Field | Type | Description | |-------|------|-------------| | `width` | integer | Image width in pixels | | `height` | integer | Image height in pixels | | `x` | integer | Horizontal offset from canvas top-left | | `y` | integer | Vertical offset from canvas top-left | ### Mask | Field | Type | Description | |-------|------|-------------| | `areas` | [Polygon](#polygon)[] | Polygonal areas to edit (optional) | | `url` | string | Black and white mask image URL (optional) | ### Polygon | Field | Type | Description | |-------|------|-------------| | `width` | integer | Image width in pixels (500-4096) | | `height` | integer | Image height in pixels (500-4096) | | `points` | integer[] | Polygon coordinates in XYXY format, clockwise from top-left | ## Example Request ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/upload-paint" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "imgUrl": "https://cdn.legnext.ai/mj/ba5d06e1-5078-4465-adc1-a4264ecdfac7_0.png", "canvas": { "width": 1024, "height": 1024 }, "imgPos": { "width": 512, "height": 512, "x": 256, "y": 256 }, "mask": { "areas": [ { "width": 500, "height": 500, "points": [ 10, 10, 10, 100, 100, 100, 100, 10 ] } ] }, "remixPrompt": "A beautiful mountain scene with trees", "callback": "https://webhook.site/d0ca59bc-35a6-4a1e-b1b1-aea7faeb7f67" }' ``` ```python Python import requests url = "https://api.legnext.ai/api/v1/upload-paint" headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } data = { "imgUrl": "https://cdn.legnext.ai/mj/ba5d06e1-5078-4465-adc1-a4264ecdfac7_0.png", "canvas": { "width": 1024, "height": 1024 }, "imgPos": { "width": 512, "height": 512, "x": 256, "y": 256 }, "mask": { "areas": [ { "width": 500, "height": 500, "points": [ 10, 10, 10, 100, 100, 100, 100, 10 ] } ] }, "remixPrompt": "A beautiful mountain scene with trees", "callback": "https://webhook.site/d0ca59bc-35a6-4a1e-b1b1-aea7faeb7f67" } response = requests.post(url, headers=headers, json=data) result = response.json() print(result) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/upload-paint', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ imgUrl: 'https://cdn.legnext.ai/mj/ba5d06e1-5078-4465-adc1-a4264ecdfac7_0.png', canvas: { width: 1024, height: 1024 }, imgPos: { width: 512, height: 512, x: 256, y: 256 }, mask: { areas: [ { width: 500, height: 500, points: [ 10, 10, 10, 100, 100, 100, 100, 10 ] } ] }, remixPrompt: 'A beautiful mountain scene with trees', callback: 'https://webhook.site/d0ca59bc-35a6-4a1e-b1b1-aea7faeb7f67' }) }); const result = await response.json(); console.log(result); ``` ## Response Returns a task object containing the task information. ```json { "job_id": "aa7bd9d9-e20d-408d-b031-46cde06ee888", "model": "midjourney", "task_type": "upload_paint", "status": "pending", "config": { "service_mode": "public", "webhook_config": { "endpoint": "https://webhook.site/d0ca59bc-35a6-4a1e-b1b1-aea7faeb7f67", "secret": "" } }, "input": null, "output": { "image_url": "", "image_urls": null, "seed": "" }, "meta": { "created_at": "", "started_at": "", "ended_at": "", "usage": { "type": "point", "frozen": 120, "consume": 0 } }, "detail": null, "logs": [], "error": { "code": 0, "raw_message": "", "message": "", "detail": null } } ``` > **Note:** This is the initial success response. Use the `job_id` to check the task status via the [Get Task](https://docs.legnext.ai/api-reference/task-management/get-task) endpoint to retrieve the completed result with image URLs. --- # Retexture _Transform image materials and textures_ **Endpoint:** `POST /v1/retexture` ## Headers | Header | Type | Required | Description | |--------|------|----------|-------------| | `x-api-key` | string | Yes | Your API key | ## Request Body | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `imgUrl` | string | Yes | URL of the source image (max length: 1024 characters) | | `remixPrompt` | string | Yes | Text description of desired texture/material transformation | | `callback` | string | No | Callback URL for task completion notifications | ## Example Requests ### Material Transformation ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/retexture" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "imgUrl": "https://example.com/image.jpg", "remixPrompt": "Convert to oil painting style", "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" }' ``` ```python Python import requests url = "https://api.legnext.ai/api/v1/retexture" headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } data = { "imgUrl": "https://example.com/image.jpg", "remixPrompt": "Convert to oil painting style", "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" } response = requests.post(url, headers=headers, json=data) result = response.json() print(result) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/retexture', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ imgUrl: 'https://i.ibb.co/yc7NvSqH/kling.jpg', remixPrompt: 'Convert to oil painting style', callback: 'https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d' }) }); const result = await response.json(); console.log(result); ``` ## Response Returns a task object containing the task information. ```json { "job_id": "d8f6a791-4d2f-4ec4-9df2-f0abb7775143", "model": "midjourney", "task_type": "retexture", "status": "pending", "config": { "service_mode": "public", "webhook_config": { "endpoint": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d", "secret": "" } }, "input": null, "output": { "image_url": "", "image_urls": null, "seed": "" }, "meta": { "created_at": "", "started_at": "", "ended_at": "", "usage": { "type": "point", "frozen": 120, "consume": 0 } }, "detail": null, "logs": [], "error": { "code": 0, "raw_message": "", "message": "", "detail": null } } ``` > **Note:** This is the initial success response. Use the `job_id` to check the task status via the [Get Task](https://docs.legnext.ai/api-reference/task-management/get-task) endpoint to retrieve the completed result with image URLs. ## Supported Formats - **Image URL**: HTTPS URLs pointing to image files (max length: 1024 characters) - **Supported Types**: JPG, PNG, WebP - **Max File Size**: 10MB --- # Remove Background _Remove backgrounds from images_ **Endpoint:** `POST /v1/remove-background` ## Headers | Header | Type | Required | Description | |--------|------|----------|-------------| | `x-api-key` | string | Yes | Your API key | ## Request Body | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `imgUrl` | string | Yes | URL of the image to process (max length: 1024 characters) | | `callback` | string | No | Callback URL for task completion notifications | ## Example Request ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/remove-background" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "imgUrl": "https://example.com/image.jpg", "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" }' ``` ```python Python import requests url = "https://api.legnext.ai/api/v1/remove-background" headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } data = { "imgUrl": "https://example.com/image.jpg", "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" } response = requests.post(url, headers=headers, json=data) result = response.json() print(result) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/remove-background', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ imgUrl: 'https://i.ibb.co/yc7NvSqH/kling.jpg', callback: 'https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d' }) }); const result = await response.json(); console.log(result); ``` ## Response Returns a task object containing the task information. ```json { "job_id": "e5a2e10b-d982-4af6-8d91-bb62f6355f36", "model": "midjourney", "task_type": "remove_background", "status": "pending", "config": { "service_mode": "public", "webhook_config": { "endpoint": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d", "secret": "" } }, "input": null, "output": { "image_url": "", "image_urls": null, "seed": "" }, "meta": { "created_at": "", "started_at": "", "ended_at": "", "usage": { "type": "point", "frozen": 80, "consume": 0 } }, "detail": null, "logs": [], "error": { "code": 0, "raw_message": "", "message": "", "detail": null } } ``` > **Note:** This is the initial success response. Use the `job_id` to check the task status via the [Get Task](https://docs.legnext.ai/api-reference/task-management/get-task) endpoint to retrieve the completed result with image URLs. --- # Enhance _Improve image quality and detail_ **Endpoint:** `POST /v1/enhance` > **Note:** **Important**: The original job must be created in draft mode. This means the original job's prompt must include the parameters: `--v 7 --draft` ## Headers | Header | Type | Required | Description | |--------|------|----------|-------------| | `x-api-key` | string | Yes | Your API key | ## Request Body | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `jobId` | string | Yes | ID of the original image generation task | | `imageNo` | integer | Yes | Image number to enhance (0/1/2/3) | | `callback` | string | No | Callback URL for task completion notifications | ## Example Request ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/enhance" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "jobId": "c6821434-5e41-408f-b42b-2562306b109c", "imageNo": 0, "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" }' ``` ```python Python import requests url = "https://api.legnext.ai/api/v1/enhance" headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } data = { "jobId": "c6821434-5e41-408f-b42b-2562306b109c", "imageNo": 0, "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" } response = requests.post(url, headers=headers, json=data) result = response.json() print(result) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/enhance', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ jobId: 'c6821434-5e41-408f-b42b-2562306b109c', imageNo: 0, callback: 'https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d' }) }); const result = await response.json(); console.log(result); ``` ## Response Returns a task object containing the task information. ```json { "job_id": "06eb333e-bd6b-4eb4-a5e9-7db1f091b728", "model": "midjourney", "task_type": "enhance", "status": "pending", "config": { "service_mode": "public", "webhook_config": { "endpoint": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d", "secret": "" } }, "input": null, "output": { "image_url": "", "image_urls": null, "seed": "" }, "meta": { "created_at": "", "started_at": "", "ended_at": "", "usage": { "type": "point", "frozen": 80, "consume": 0 } }, "detail": null, "logs": [], "error": { "code": 0, "raw_message": "", "message": "", "detail": null } } ``` > **Note:** This is the initial success response. Use the `job_id` to check the task status via the [Get Task](https://docs.legnext.ai/api-reference/task-management/get-task) endpoint to retrieve the completed result with image URLs. --- # Video Diffusion _Generate videos from text or images_ **Endpoint:** `POST /v1/video-diffusion` ## Headers | Header | Type | Required | Description | |--------|------|----------|-------------| | `x-api-key` | string | Yes | Your API key | ## Request Body ## Image-to-Video Mode Choose one of two input methods: **Option 1: Using existing generated image** | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `jobId` | string | Yes | ID of the source image generation task | | `imageNo` | integer | Yes | Image number to animate (0/1/2/3) | | `prompt` | string | No | Video generation prompt text (1-8192 characters) | | `videoType` | integer | No | Video quality type (0: 480p, 1: 720p) | | `callback` | string | No | Callback URL for task completion notifications | **Option 2: Using prompt with image URL** | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `prompt` | string | Yes | Video generation prompt text with image URL included, format: "[image_url] your prompt text" (1-8192 characters) | | `videoType` | integer | No | Video quality type (0: 480p, 1: 720p) | | `callback` | string | No | Callback URL for task completion notifications | ## Video Types | Value | Resolution | Description | |-------|------------|-------------| | 0 | 480p | Standard definition (default) | | 1 | 720p | High definition | ## Advanced Parameters You can add these parameters to your prompt for more control over video generation: ### Motion Intensity Control the amount of movement in the generated video: - **Low Motion** (default): Static scenes with subtle movements - Add `--motion low` to your prompt - **High Motion**: Large camera movements and dramatic motion (may produce artistic effects) - Add `--motion high` to your prompt **Example:** ``` "https://example.com/image.jpg A cinematic landscape --motion high" ``` ### Raw Mode Reduce automatic system enhancements for more precise control over the output: - Add `--raw` to your prompt **Example:** ``` "https://example.com/image.jpg A peaceful sunset scene --raw" ``` ### End Frame Image Specify the final frame of your video by providing an image URL: - Add `--end [image_url]` to your prompt **Example:** ``` "https://example.com/start.jpg A transformation sequence --end https://example.com/end.jpg" ``` ### Video Loop Generate a video where the last frame matches the first frame, creating a seamless loop: - Add `--loop` to your prompt **Example:** ``` "https://example.com/image.jpg Rotating product display --loop" ``` ### Batch Size Control the number of videos generated in a single task. This affects the cost accordingly: - Add `--bs [1|2|4]` to your prompt - Valid values: 1, 2, or 4 - Default: 4 **Example:** ``` "https://example.com/image.jpg A dynamic animation --bs 2" ``` ### Combining Parameters You can combine multiple parameters in a single prompt: **Example:** ``` "https://example.com/image.jpg Epic camera movement through the scene --motion high --raw --loop --bs 1" ``` ## Example Requests ### Image-to-Video (Using existing image) ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/video-diffusion" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "jobId": "c6821434-5e41-408f-b42b-2562306b109c", "imageNo": 0, "prompt": "Make this image move with gentle animation", "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d", "videoType": 0 }' ``` ```python Python import requests url = "https://api.legnext.ai/api/v1/video-diffusion" headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } data = { "jobId": "c6821434-5e41-408f-b42b-2562306b109c", "imageNo": 0, "prompt": "Make this image move with gentle animation", "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d", "videoType": 0 } response = requests.post(url, headers=headers, json=data) result = response.json() print(result) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/video-diffusion', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ jobId: 'c6821434-5e41-408f-b42b-2562306b109c', imageNo: 0, prompt: 'Make this image move with gentle animation', callback: 'https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d', videoType: 0 }) }); const result = await response.json(); console.log(result); ``` ### Image-to-Video (Using image URL) ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/video-diffusion" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "prompt": "https://example.com/image.jpg A cinematic shot of ocean waves crashing against rocks", "videoType": 1, "callback": "https://webhook.site/d0ca59bc-35a6-4a1e-b1b1-aea7faeb7f67" }' ``` ```python Python import requests url = "https://api.legnext.ai/api/v1/video-diffusion" headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } data = { "prompt": "https://example.com/image.jpg A cinematic shot of ocean waves crashing against rocks", "videoType": 1, "callback": "https://webhook.site/d0ca59bc-35a6-4a1e-b1b1-aea7faeb7f67" } response = requests.post(url, headers=headers, json=data) result = response.json() print(result) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/video-diffusion', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt: 'https://example.com/image.jpg A cinematic shot of ocean waves crashing against rocks', videoType: 1, callback: 'https://webhook.site/d0ca59bc-35a6-4a1e-b1b1-aea7faeb7f67' }) }); const result = await response.json(); console.log(result); ``` ## Response Returns a task object containing the task information. ```json { "job_id": "d55cb628-3f71-4be8-bea1-4e01319b6589", "model": "midjourney", "task_type": "video_diffusion", "status": "pending", "config": { "service_mode": "public", "webhook_config": { "endpoint": "https://webhook.site/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "secret": "" } }, "input": null, "output": { "video_urls": null, "seed": "" }, "meta": { "created_at": "", "started_at": "", "ended_at": "", "usage": { "type": "point", "frozen": 480, "consume": 0 } }, "detail": null, "logs": [], "error": { "code": 0, "raw_message": "", "message": "", "detail": null } } ``` > **Note:** This is the initial success response. Use the `job_id` to check the task status via the [Get Task](https://docs.legnext.ai/api-reference/task-management/get-task) endpoint to retrieve the completed result with video URLs. --- # Extend Video _Extend video duration with new frames_ **Endpoint:** `POST /v1/extend-video` Each extension adds 4 seconds to the video duration, with a maximum of 4 extensions (creating up to 21-second videos). ## Headers | Header | Type | Required | Description | |--------|------|----------|-------------| | `x-api-key` | string | Yes | Your API key | ## Request Body | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `jobId` | string | Yes | ID of the original video generation task | | `videoNo` | integer | Yes | Video number to extend (0/1/2/3) | | `prompt` | string | No | Text prompt to guide the extension (1-8192 characters) | | `callback` | string | No | Callback URL for task completion notifications | ## Example Request ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/extend-video" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "jobId": "b24ffa07-7b76-49a2-963e-f6c527f7cec7", "videoNo": 0, "prompt": "Continue with more dynamic movement and effects", "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" }' ``` ```python Python import requests url = "https://api.legnext.ai/api/v1/extend-video" headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } data = { "jobId": "b24ffa07-7b76-49a2-963e-f6c527f7cec7", "videoNo": 0, "prompt": "Continue with more dynamic movement and effects", "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" } response = requests.post(url, headers=headers, json=data) result = response.json() print(result) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/extend-video', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ jobId: 'b24ffa07-7b76-49a2-963e-f6c527f7cec7', videoNo: 0, prompt: 'Continue with more dynamic movement and effects', callback: 'https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d' }) }); const result = await response.json(); console.log(result); ``` ## Response Returns a task object containing the task information. ```json { "job_id": "e41e5586-dcee-4659-ae56-dbf19d20051a", "model": "midjourney", "task_type": "extend_video", "status": "pending", "config": { "service_mode": "public", "webhook_config": { "endpoint": "https://webhook.site/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "secret": "" } }, "input": null, "output": { "video_urls": null, "seed": "" }, "meta": { "created_at": "", "started_at": "", "ended_at": "", "usage": { "type": "point", "frozen": 480, "consume": 0 } }, "detail": null, "logs": [], "error": { "code": 0, "raw_message": "", "message": "", "detail": null } } ``` > **Note:** This is the initial success response. Use the `job_id` to check the task status via the [Get Task](https://docs.legnext.ai/api-reference/task-management/get-task) endpoint to retrieve the completed result with video URLs. --- # Video Upscale _Enhance video resolution and quality_ **Endpoint:** `POST /v1/video-upscale` ## Headers | Header | Type | Required | Description | |--------|------|----------|-------------| | `x-api-key` | string | Yes | Your API key | ## Request Body | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `jobId` | string | Yes | ID of the original video generation task | | `videoNo` | integer | Yes | Video number to upscale (0/1/2/3) | | `callback` | string | No | Callback URL for task completion notifications | ## Example Request ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/video-upscale" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "jobId": "b24ffa07-7b76-49a2-963e-f6c527f7cec7", "videoNo": 0, "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" }' ``` ```python Python import requests url = "https://api.legnext.ai/api/v1/video-upscale" headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } data = { "jobId": "b24ffa07-7b76-49a2-963e-f6c527f7cec7", "videoNo": 0, "callback": "https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d" } response = requests.post(url, headers=headers, json=data) result = response.json() print(result) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/video-upscale', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ jobId: 'b24ffa07-7b76-49a2-963e-f6c527f7cec7', videoNo: 0, callback: 'https://webhook.site/c98cb890-fb92-439f-8d60-42c8a51eb52d' }) }); const result = await response.json(); console.log(result); ``` ## Response Returns a task object containing the task information. ```json { "job_id": "2cbffb65-10ac-45a2-91d4-19a19a19ab4c", "model": "midjourney", "task_type": "video_upscale", "status": "pending", "config": { "service_mode": "public", "webhook_config": { "endpoint": "https://webhook.site/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "secret": "" } }, "input": null, "output": { "video_urls": null, "seed": "" }, "meta": { "created_at": "", "started_at": "", "ended_at": "", "usage": { "type": "point", "frozen": 480, "consume": 0 } }, "detail": null, "logs": [], "error": { "code": 0, "raw_message": "", "message": "", "detail": null } } ``` > **Note:** This is the initial success response. Use the `job_id` to check the task status via the [Get Task](https://docs.legnext.ai/api-reference/task-management/get-task) endpoint to retrieve the completed result with video URLs. --- # Topaz Upscale Image _Upscale images to ultra-high resolutions up to 12K_ **Endpoint:** `POST /v1/enhance-upscale` > **Note:** Supports direct image URLs or images from previous Midjourney tasks. ## Input Methods Choose one of the following input methods: ### Option 1: Direct Image URL | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `image_url` | string | Yes | Publicly accessible image URL (HTTP/HTTPS). Supports JPEG, PNG, TIFF. Max: 100MB | ### Option 2: Midjourney Task | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `jobId` | string | Yes | ID from previous Midjourney task | | `imageNo` | integer | Yes | Image index from grid (0-3) | ### Common Parameters All enhancement requests support the following parameters: | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `target_resolution` | string | `2K` | Output resolution: `HD`, `FHD`, `2K`, `4K`, `6K`, `8K`, `12K` | | `content_type` | string | `standard` | Enhancement model: `standard`, `photo`, `illustration`, `text`, `low_res` | | `aspect_ratio` | string | `keep` | Aspect ratio: `keep`, `1:1`, `16:9`, `9:16`, `4:5`, `5:4`, `3:2`, `2:3`, `4:3`, `3:4` | | `crop_mode` | string | `letterbox` | Crop handling: `letterbox`, `crop`, `stretch` | | `output_format` | string | `jpeg` | Output format: `jpeg`, `jpg`, `png`, `tiff`, `tif` | | `face_enhancement_level` | string | `moderate` | Face enhancement: `off`, `none`, `subtle`, `moderate`, `strong` | | `callback` | string | - | Webhook URL for completion notifications | ## Resolution Options | Resolution | Long Edge | Credits | Cost | Recommended For | |------------|-----------|---------|------|-----------------| | HD/FHD | 1920px | 120 | $0.12 | Web, social media | | 2K | 2560px | 120 | $0.12 | Web, social media (default) | | 4K | 3840px | 160 | $0.16 | Digital displays | | 6K | 6144px | 200 | $0.20 | Professional printing | | 8K | 7680px | 300 | $0.30 | Large format prints | | 12K | 12288px | 540 | $0.54 | Billboards, posters | > **Warning:** Higher resolutions consume more credits and take longer to process. Choose the minimum resolution that meets your requirements. ## Content Type Models | Type | Best For | |------|----------| | `standard` | General purpose, mixed content (default) | | `photo` | Photographs, realistic images | | `illustration` | Digital art, CGI, drawings | | `text` | Documents, screenshots with text | | `low_res` | Very low quality source images | ## Face Enhancement | Level | Effect | |-------|--------| | `off` / `none` | Disabled (no faces in image) | | `subtle` | Gentle enhancement for natural portraits | | `moderate` | Balanced enhancement (default) | | `strong` | Aggressive enhancement for low-quality faces | ## Examples ### Using Image URL ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/enhance-upscale" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "image_url": "https://example.com/photo.jpg", "target_resolution": "4K", "content_type": "photo" }' ``` ```python Python import requests response = requests.post( "https://api.legnext.ai/api/v1/enhance-upscale", headers={"x-api-key": "YOUR_API_KEY"}, json={ "image_url": "https://example.com/photo.jpg", "target_resolution": "4K", "content_type": "photo" } ) print(response.json()) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/enhance-upscale', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ image_url: 'https://example.com/photo.jpg', target_resolution: '4K', content_type: 'photo' }) }); console.log(await response.json()); ``` ### Using Midjourney Task ```bash cURL curl -X POST "https://api.legnext.ai/api/v1/enhance-upscale" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "jobId": "1868588555208310784", "imageNo": 0, "target_resolution": "8K", "content_type": "illustration" }' ``` ```python Python import requests response = requests.post( "https://api.legnext.ai/api/v1/enhance-upscale", headers={"x-api-key": "YOUR_API_KEY"}, json={ "jobId": "1868588555208310784", "imageNo": 0, "target_resolution": "8K", "content_type": "illustration" } ) print(response.json()) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/v1/enhance-upscale', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ jobId: '1868588555208310784', imageNo: 0, target_resolution: '8K', content_type: 'illustration' }) }); console.log(await response.json()); ``` ## Response ### Success Response Returns a task object with the following structure: ```json { "job_id": "f3efd852-18ad-483d-87f2-0685a60df014", "model": "midjourney", "task_type": "enhance_upscale", "status": "pending", "config": { "service_mode": "public", "webhook_config": { "endpoint": "", "secret": "" } }, "input": null, "output": { "image_url": "", "image_urls": null, "seed": "" }, "meta": { "created_at": "2025-12-17T03:22:29+08:00", "started_at": "0001-01-01T00:00:00Z", "ended_at": "0001-01-01T00:00:00Z", "usage": { "type": "point", "frozen": 300, "consume": 0 } }, "detail": null, "logs": [], "error": { "code": 0, "raw_message": "", "message": "", "detail": null } } ``` ### Response Fields | Field | Type | Description | |-------|------|-------------| | `job_id` | string | Unique task identifier (UUID) | | `model` | string | Model used: `midjourney` | | `task_type` | string | Task type: `enhance_upscale` | | `status` | string | Current status: `pending`, `processing`, `completed`, `failed` | | `config` | object | Service configuration | | `config.service_mode` | string | Service mode: `public` | | `config.webhook_config` | object | Webhook configuration | | `config.webhook_config.endpoint` | string | Webhook endpoint URL (empty if not set) | | `config.webhook_config.secret` | string | Webhook secret (empty if not set) | | `input` | object/null | Input parameters (null for this endpoint) | | `output` | object | Task output (empty until completed) | | `output.image_url` | string | Primary enhanced image URL (available when `status` is `completed`) | | `output.image_urls` | array/null | Array of enhanced image URLs (null until completed) | | `output.seed` | string | Generation seed (empty for enhancement tasks) | | `meta` | object | Task metadata | | `meta.created_at` | string | Task creation timestamp (ISO 8601) | | `meta.started_at` | string | Task start timestamp (ISO 8601, `0001-01-01T00:00:00Z` if not started) | | `meta.ended_at` | string | Task completion timestamp (ISO 8601, `0001-01-01T00:00:00Z` if not completed) | | `meta.usage` | object | Credit usage information | | `meta.usage.type` | string | Usage type: `point` | | `meta.usage.frozen` | integer | Credits frozen/reserved for this task | | `meta.usage.consume` | integer | Credits actually consumed (0 if task failed) | | `detail` | object/null | Additional task details (null if none) | | `logs` | array | Processing logs (empty array) | | `error` | object | Error information | | `error.code` | integer | Error code (0 if successful) | | `error.raw_message` | string | Raw error message from service (empty if successful) | | `error.message` | string | Human-readable error message (empty if successful) | | `error.detail` | object/null | Additional error details (null if none) | > **Note:** Use the `job_id` to check task status via the [Get Task Status](https://docs.legnext.ai/api-reference/task-management/get-task) endpoint. --- # Get Task _Retrieve job status and results_ **Endpoint:** `GET /v1/job/{job_id}` ## Status Values | Status | Description | |--------|-------------| | `pending` | Job is queued and waiting to be processed | | `staged` | Job is prepared and staged for processing | | `processing` | Job is currently being processed | | `failed` | Job has failed due to an error | | `completed` | Job has completed successfully | ## Headers | Header | Type | Required | Description | |--------|------|----------|-------------| | `x-api-key` | string | Yes | Your API key | ## Path Parameters | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `job_id` | string | Yes | The unique identifier of the job | ## Example Request ```bash cURL curl -X GET "https://api.legnext.ai/api/v1/job/98761286-cdc7-4085-abfe-c9f149ff722b" \ -H "x-api-key: YOUR_API_KEY" ``` ```python Python import requests job_id = "98761286-cdc7-4085-abfe-c9f149ff722b" url = f"https://api.legnext.ai/api/v1/job/{job_id}" headers = { "x-api-key": "YOUR_API_KEY" } response = requests.get(url, headers=headers) result = response.json() print(result) ``` ```javascript JavaScript const jobId = '98761286-cdc7-4085-abfe-c9f149ff722b'; const response = await fetch(`https://api.legnext.ai/api/v1/job/${jobId}`, { method: 'GET', headers: { 'x-api-key': 'YOUR_API_KEY' } }); const result = await response.json(); console.log(result); ``` ## Response Returns the complete job information including current status and results. ```json { "job_id": "a616de55-6130-4e1f-b8cd-531ed0599353", "model": "midjourney", "task_type": "diffusion", "status": "completed", "config": { "service_mode": "public", "webhook_config": { "endpoint": "https://webhook.site/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "secret": "" } }, "input": null, "output": { "image_url": "https://cdn.legnext.ai/temp/1760408558306.png", "image_urls": [ "https://cdn.legnext.ai/mj/a616de55-6130-4e1f-b8cd-531ed0599353_0.png", "https://cdn.legnext.ai/mj/a616de55-6130-4e1f-b8cd-531ed0599353_1.png", "https://cdn.legnext.ai/mj/a616de55-6130-4e1f-b8cd-531ed0599353_2.png", "https://cdn.legnext.ai/mj/a616de55-6130-4e1f-b8cd-531ed0599353_3.png" ], "seed": "1904983176", "available_actions": { "edit": [ 0, 1, 2, 3 ], "inpaint": [ 0, 1, 2, 3 ], "outpaint": [ 0, 1, 2, 3 ], "pan": [ 0, 1, 2, 3 ], "remix": [ 0, 1, 2, 3 ], "reroll": true, "upscale": [ 0, 1, 2, 3 ], "variation": [ 0, 1, 2, 3 ] } }, "meta": { "created_at": "2025-10-14T02:22:04Z", "started_at": "2025-10-14T02:22:06Z", "ended_at": "2025-10-14T02:22:50Z", "usage": { "type": "point", "frozen": 80, "consume": 80 } }, "detail": null, "logs": [], "error": { "code": 0, "raw_message": "", "message": "", "detail": null } } ``` --- # Get Account Balance _Check account balance and credits_ **Endpoint:** `GET /account/balance` ## Overview Check your account balance, available credits, points, and low balance alert settings. ## Request ### Headers | Header | Type | Required | Description | |--------|------|----------|-------------| | `x-api-key` | string | Yes | Your API key for authentication | ### Example Request ```bash cURL curl --location 'https://api.legnext.ai/api/account/balance' \ --header 'x-api-key: YOUR_API_KEY' ``` ```python Python import requests url = "https://api.legnext.ai/api/account/balance" headers = { "x-api-key": "YOUR_API_KEY" } response = requests.get(url, headers=headers) result = response.json() print(result) ``` ```javascript JavaScript const response = await fetch('https://api.legnext.ai/api/account/balance', { method: 'GET', headers: { 'x-api-key': 'YOUR_API_KEY' } }); const result = await response.json(); console.log(result); ``` ## Response ### Response Fields | Field | Type | Description | |-------|------|-------------| | `code` | integer | Response status code (200 for success) | | `message` | string | Response message | | `data` | object | Account balance data | | `data.account_id` | integer | Your account identifier | | `data.balance_usd` | float | Current balance in USD | | `data.available_credits` | integer | Available credits for API usage | | `data.available_points` | integer | Available points | | `data.alert_threshold` | integer | Low balance alert threshold in USD | | `data.low_balance_alert` | boolean | Whether low balance alert is triggered | | `data.updated_at` | string | Last update timestamp (ISO 8601 format) | ### Example Response ```json { "code": 200, "data": { "account_id": 1, "balance_usd": 72.048, "available_credits": 71000, "available_points": 1048, "alert_threshold": 10, "low_balance_alert": false, "updated_at": "2025-11-05T08:22:37.784663288Z" }, "message": "success" } ``` ## Understanding Your Balance - **balance_usd**: Your current account balance in US dollars - **available_credits**: Credits that can be used for API operations - **available_points**: Bonus points or promotional credits - **alert_threshold**: You'll receive alerts when balance falls below this amount - **low_balance_alert**: Indicates if your balance is currently below the threshold ## Notes - Check your balance regularly to ensure uninterrupted service - Set up webhook notifications for low balance alerts - Credits are deducted based on the API operations you perform --- # SDK Overview _Explore Legnext SDKs for easy API integration_ Official SDKs for the Legnext AI API - Professional image and video generation. ## Available SDKs - **[Python](https://docs.legnext.ai/sdk/python/installation)**: Official Python SDK with async support and type hints - **[JavaScript/Node.js](https://docs.legnext.ai/sdk/javascript/installation)**: TypeScript/JavaScript SDK with axios and full type definitions - **[Go](https://docs.legnext.ai/sdk/go/installation)**: Go SDK with context support and concurrent-safe operations - **[Java](https://docs.legnext.ai/sdk/java/installation)**: Java SDK compatible with Java 1.8+ and Maven/Gradle - **[PHP](https://docs.legnext.ai/sdk/php/installation)**: PHP SDK with Composer support for PHP 7.4+ - **[Ruby](https://docs.legnext.ai/sdk/ruby/installation)**: Ruby SDK with RubyGems and Bundler support - **[C#/.NET](https://docs.legnext.ai/sdk/csharp/installation)**: .NET SDK for C# with async/await and NuGet support - **[Rust](https://docs.legnext.ai/sdk/rust/installation)**: Rust SDK with async/await and Cargo support --- ## Why Use an SDK? SDKs provide: - **Type Safety** - Full type hints and IDE autocomplete - **Error Handling** - Built-in exception handling - **Convenience** - No manual header or auth setup - **Best Practices** - Language-specific conventions --- ## Features All SDKs include: - 🚀 Easy-to-use client libraries - 🔐 Built-in authentication handling - 🔗 Support for all API endpoints - ✅ Comprehensive error handling - 📝 Complete documentation --- # Installation _Install the Legnext Python SDK_ ## Install from PyPI ```bash python -m pip install legnext ``` ## Verify Installation ```bash python -c "import legnext; print(legnext.__version__)" ``` ## Requirements - Python 3.10 or higher - httpx >= 0.27.0 - pydantic >= 2.0.0 --- ## Next Steps - [Set up Authentication](https://docs.legnext.ai/sdk/python/authentication) - [Quick Start](https://docs.legnext.ai/sdk/python/quickstart) --- # Authentication _Set up authentication for the Legnext Python SDK_ ## Get Your API Key 1. Visit [Legnext Dashboard](https://dashboard.legnext.ai) 2. Log in to your account 3. Navigate to **API Keys** section 4. Create a new API key 5. Copy and save it securely ## Using Your API Key ### Method 1: Direct Initialization ```python from legnext import Client client = Client(api_key="your-api-key-here") ``` ### Method 2: Environment Variable (Recommended) Set the environment variable: ```bash # macOS/Linux export LEGNEXT_API_KEY="your-api-key-here" # Windows PowerShell $env:LEGNEXT_API_KEY="your-api-key-here" ``` Then in your code: ```python import os from legnext import Client client = Client(api_key=os.getenv("LEGNEXT_API_KEY")) ``` ### Method 3: .env File Create a `.env` file: ```env LEGNEXT_API_KEY=your-api-key-here ``` Load it in your code: ```python from dotenv import load_dotenv import os from legnext import Client load_dotenv() client = Client(api_key=os.getenv("LEGNEXT_API_KEY")) ``` ## Security Best Practices ⚠️ **Never hardcode API keys in your code** ✅ **Always use environment variables or .env files** ✅ **Add `.env` to `.gitignore` to prevent accidental commits** ✅ **Rotate keys regularly and revoke compromised ones** --- ## Next Steps - [Quick Start](https://docs.legnext.ai/sdk/python/quickstart) - [Image Generation API](https://docs.legnext.ai/sdk/python/image-generation) --- # Quick Start _Get started with the Legnext Python SDK in 5 minutes_ ## 1. Install ```bash pip install legnext ``` ## 2. Set API Key ```bash export LEGNEXT_API_KEY="your-api-key" ``` ## 3. Basic Example ```python import os from legnext import Client client = Client(api_key=os.getenv("LEGNEXT_API_KEY")) # Generate image response = client.midjourney.diffusion( text="a beautiful sunset over mountains" ) # Wait for completion result = client.tasks.wait_for_completion(response.job_id) print(f"Images: {result.output.image_urls}") ``` That's it! Your first API call is complete. --- ## Next Steps - **Polling** - Use `client.tasks.wait_for_completion()` with `on_progress` callback - **Webhooks** - Set `callback` parameter for async notifications - **API Methods** - See [Image Generation](https://docs.legnext.ai/sdk/python/image-generation) reference - **Async** - Learn about `AsyncClient` in [Task Management](https://docs.legnext.ai/sdk/python/task-management) - **Errors** - See error handling in [Task Management](https://docs.legnext.ai/sdk/python/task-management) --- ## Common Use Cases **Generate and upscale:** ```python response = client.midjourney.diffusion(text="...") result = client.tasks.wait_for_completion(response.job_id) upscale = client.midjourney.upscale( job_id=response.job_id, image_no=0 ) ``` **With webhook (production):** ```python response = client.midjourney.diffusion( text="...", callback="https://your-api.com/webhooks/image" ) print(f"Job {response.job_id} will post to your webhook") ``` **Async batch:** ```python import asyncio from legnext import AsyncClient async with AsyncClient(api_key=os.getenv("LEGNEXT_API_KEY")) as client: responses = await asyncio.gather(*[ client.midjourney.diffusion(text=f"prompt {i}") for i in range(5) ]) ``` --- ## Learn More - [Installation Details](https://docs.legnext.ai/sdk/python/installation) - [Authentication Guide](https://docs.legnext.ai/sdk/python/authentication) - [Image Generation API](https://docs.legnext.ai/sdk/python/image-generation) - [Video Generation API](https://docs.legnext.ai/sdk/python/video-generation) - [Task Management & Error Handling](https://docs.legnext.ai/sdk/python/task-management) --- # Image Generation _Image generation API reference_ ## diffusion(text, callback=None) Create a new text-to-image generation task. ```python response = client.midjourney.diffusion( text="a serene mountain landscape at sunset", callback="https://your-domain.com/webhook" # Optional ) ``` **Parameters:** - `text` (str): Text prompt (1-8192 characters) - `callback` (str, optional): Webhook URL **Returns:** `TaskResponse` with `job_id` and `status` --- --- ## variation(job_id, image_no, type, remix_prompt=None, callback=None) Create variations of a generated image. ```python response = client.midjourney.variation( job_id="original-job-id", image_no=0, type=1, # 0=Subtle, 1=Strong remix_prompt="add more clouds", callback="https://your-domain.com/webhook" # Optional ) ``` **Parameters:** - `job_id` (str): Original image task ID - `image_no` (int): Image index (0-3) - `type` (int): Variation intensity (0=Subtle, 1=Strong) - `remix_prompt` (str, optional): Additional guidance - `callback` (str, optional): Webhook URL --- ## upscale(job_id, image_no, type, callback=None) Upscale a generated image. ```python response = client.midjourney.upscale( job_id="original-job-id", image_no=0, type=1, # 0=Subtle, 1=Creative callback="https://your-domain.com/webhook" # Optional ) ``` **Parameters:** - `job_id` (str): Original image task ID - `image_no` (int): Image index (0-3) - `type` (int): Upscaling type (0=Subtle, 1=Creative) - `callback` (str, optional): Webhook URL --- ## reroll(job_id, callback=None) Regenerate with the same prompt. ```python response = client.midjourney.reroll( job_id="original-job-id", callback="https://your-domain.com/webhook" # Optional ) ``` **Parameters:** - `job_id` (str): Original image task ID - `callback` (str, optional): Webhook URL --- ## blend(img_urls, aspect_ratio, callback=None) Blend 2-5 images together. ```python response = client.midjourney.blend( img_urls=[ "https://example.com/image1.png", "https://example.com/image2.png" ], aspect_ratio="1:1", # "2:3", "1:1", or "3:2" callback="https://your-domain.com/webhook" # Optional ) ``` **Parameters:** - `img_urls` (list): List of 2-5 image URLs - `aspect_ratio` (str): Image ratio ("2:3", "1:1", or "3:2") - `callback` (str, optional): Webhook URL --- ## describe(img_url, callback=None) Generate text descriptions from an image. ```python response = client.midjourney.describe( img_url="https://example.com/image.png", callback="https://your-domain.com/webhook" # Optional ) ``` **Parameters:** - `img_url` (str): URL of image to describe - `callback` (str, optional): Webhook URL --- ## shorten(prompt, callback=None) Optimize and shorten a prompt. ```python response = client.midjourney.shorten( prompt="a very detailed and long prompt text...", callback="https://your-domain.com/webhook" # Optional ) ``` **Parameters:** - `prompt` (str): Prompt text to optimize - `callback` (str, optional): Webhook URL --- ## pan(job_id, image_no, direction, scale, remix_prompt=None, callback=None) Extend image in a specific direction. ```python response = client.midjourney.pan( job_id="original-job-id", image_no=0, direction=0, # 0=Down, 1=Right, 2=Up, 3=Left scale=1.5, # 1.1-3.0 remix_prompt="add mountains", callback="https://your-domain.com/webhook" # Optional ) ``` **Parameters:** - `job_id` (str): Original image task ID - `image_no` (int): Image index (0-3) - `direction` (int): Direction to pan (0=Down, 1=Right, 2=Up, 3=Left) - `scale` (float): Expansion scale (1.1-3.0) - `remix_prompt` (str, optional): Additional guidance - `callback` (str, optional): Webhook URL --- ## outpaint(job_id, image_no, scale, remix_prompt=None, callback=None) Expand image in all directions. ```python response = client.midjourney.outpaint( job_id="original-job-id", image_no=0, scale=1.3, # 1.1-2.0 remix_prompt="add forest background", callback="https://your-domain.com/webhook" # Optional ) ``` **Parameters:** - `job_id` (str): Original image task ID - `image_no` (int): Image index (0-3) - `scale` (float): Expansion scale (1.1-2.0) - `remix_prompt` (str, optional): Additional guidance - `callback` (str, optional): Webhook URL --- ## inpaint(job_id, image_no, mask, remix_prompt=None, callback=None) Edit specific regions using a mask. ```python with open("mask.png", "rb") as f: mask_data = f.read() response = client.midjourney.inpaint( job_id="original-job-id", image_no=0, mask=mask_data, remix_prompt="add a rainbow in the sky", callback="https://your-domain.com/webhook" # Optional ) ``` **Parameters:** - `job_id` (str): Original image task ID - `image_no` (int): Image index (0-3) - `mask` (bytes): Binary mask data (PNG format) - `remix_prompt` (str, optional): Description of edits - `callback` (str, optional): Webhook URL --- ## remix(job_id, image_no, remix_prompt, mode=None, callback=None) Transform image with a new prompt. ```python response = client.midjourney.remix( job_id="original-job-id", image_no=0, remix_prompt="turn into a watercolor painting", mode=0, # 0=Strong, 1=Subtle callback="https://your-domain.com/webhook" # Optional ) ``` **Parameters:** - `job_id` (str): Original image task ID - `image_no` (int): Image index (0-3) - `remix_prompt` (str): New prompt for transformation - `mode` (int, optional): Remix strength (0=Strong, 1=Subtle) - `callback` (str, optional): Webhook URL --- ## edit(job_id, image_no, canvas, img_pos, remix_prompt, mask=None, callback=None) Edit with canvas positioning. ```python from legnext.types import Canvas, CanvasImg, Mask, Polygon response = client.midjourney.edit( job_id="original-job-id", image_no=0, canvas=Canvas(width=1024, height=1024), img_pos=CanvasImg(width=512, height=512, x=256, y=256), remix_prompt="change the sky to sunset colors", mask=Mask(areas=[ Polygon(width=1024, height=1024, points=[100, 100, 500, 100, 500, 500, 100, 500]) ]), callback="https://your-domain.com/webhook" # Optional ) ``` **Parameters:** - `job_id` (str): Original image task ID - `image_no` (int): Image index (0-3) - `canvas` (Canvas): Canvas dimensions (width, height) - `img_pos` (CanvasImg): Image positioning on canvas - `remix_prompt` (str): Description of edits - `mask` (Mask, optional): Mask with polygon areas - `callback` (str, optional): Webhook URL --- ## upload_paint(img_url, canvas, img_pos, remix_prompt, mask, callback=None) Advanced painting on uploaded images. ```python from legnext.types import Canvas, CanvasImg, Mask response = client.midjourney.upload_paint( img_url="https://example.com/image.png", canvas=Canvas(width=1024, height=1024), img_pos=CanvasImg(width=768, height=768, x=128, y=128), remix_prompt="add magical effects", mask=Mask(url="https://example.com/mask.png"), callback="https://your-domain.com/webhook" # Optional ) ``` **Parameters:** - `img_url` (str): URL of image to paint on - `canvas` (Canvas): Canvas dimensions (width, height) - `img_pos` (CanvasImg): Image positioning on canvas - `remix_prompt` (str): Description of effects - `mask` (Mask): Mask with URL - `callback` (str, optional): Webhook URL --- ## retexture(img_url, remix_prompt, callback=None) Change textures and surfaces. ```python response = client.midjourney.retexture( img_url="https://example.com/image.png", remix_prompt="metallic and shiny surfaces", callback="https://your-domain.com/webhook" # Optional ) ``` **Parameters:** - `img_url` (str): URL of image to retexture - `remix_prompt` (str): Texture description - `callback` (str, optional): Webhook URL --- ## remove_background(img_url, callback=None) Remove the background from an image. ```python response = client.midjourney.remove_background( img_url="https://example.com/image.png", callback="https://your-domain.com/webhook" # Optional ) ``` **Parameters:** - `img_url` (str): URL of image to process - `callback` (str, optional): Webhook URL --- ## enhance(job_id, image_no, callback=None) Enhance image quality (draft to high-res). ```python response = client.midjourney.enhance( job_id="draft-job-id", image_no=0, callback="https://your-domain.com/webhook" # Optional ) ``` **Parameters:** - `job_id` (str): Original image task ID - `image_no` (int): Image index (0-3) - `callback` (str, optional): Webhook URL --- ## Next Steps - [Video Generation](https://docs.legnext.ai/sdk/python/video-generation) - [Task Management](https://docs.legnext.ai/sdk/python/task-management) --- # Video Generation _Video generation API reference_ ## video_diffusion(prompt=None, job_id=None, image_no=None, video_type=None, callback=None) Generate a video from text prompt, image URL, or animate existing generated image. ```python # Generate from text only response = client.midjourney.video_diffusion( prompt="a flowing river through mountains", video_type=1, # Optional: 0=480p, 1=720p callback="https://your-domain.com/webhook" ) # Generate from image URL in prompt response = client.midjourney.video_diffusion( prompt="https://example.com/image.png a flowing river through mountains", video_type=1, callback="https://your-domain.com/webhook" ) # Animate existing generated image response = client.midjourney.video_diffusion( job_id="original-image-job-id", image_no=0, video_type=1, callback="https://your-domain.com/webhook" ) ``` **Parameters:** - `prompt` (str, optional): Video prompt or "[image_url] prompt text" (1-8192 characters) - `job_id` (str, optional): Job ID of previously generated image - `image_no` (int, optional): Image index (0-3) when using job_id - `video_type` (int, optional): Quality (0=480p, 1=720p) - `callback` (str, optional): Webhook URL **Returns:** `TaskResponse` with `job_id` and `status` --- ## extend_video(job_id, video_no, prompt=None, callback=None) Extend an existing video. ```python response = client.midjourney.extend_video( job_id="original-video-job-id", video_no=0, prompt="continue with dramatic lighting", callback="https://your-domain.com/webhook" ) ``` **Parameters:** - `job_id` (str): Original video task ID - `video_no` (int): Video index (0-3) - `prompt` (str, optional): Extension prompt (1-8192 characters) - `callback` (str, optional): Webhook URL --- ## video_upscale(job_id, video_no, callback=None) Upscale video to higher resolution. ```python response = client.midjourney.video_upscale( job_id="original-video-job-id", video_no=0, callback="https://your-domain.com/webhook" ) ``` **Parameters:** - `job_id` (str): Original video task ID - `video_no` (int): Video index (0-3) - `callback` (str, optional): Webhook URL --- ## Next Steps - [Image Generation](https://docs.legnext.ai/sdk/python/image-generation) - [Task Management](https://docs.legnext.ai/sdk/python/task-management) --- # Task Management _Task status, async/await, and error handling_ ## tasks.get(job_id) Get current task status: ```python task = client.tasks.get(job_id="job-123") print(f"Status: {task.status}") ``` ## tasks.wait_for_completion(job_id, timeout=300, poll_interval=3, on_progress=None) Wait for task completion: ```python result = client.tasks.wait_for_completion( job_id="job-123", timeout=600, on_progress=lambda t: print(f"Progress: {t.progress}%") ) ``` **Parameters:** - `job_id` (str): Job ID to wait for - `timeout` (float, optional): Max wait time in seconds (default: 300) - `poll_interval` (float, optional): Seconds between checks (default: 3) - `on_progress` (callable, optional): Callback on each check --- # Async/Await All methods support async using `AsyncClient`: ```python import asyncio from legnext import AsyncClient async def main(): async with AsyncClient(api_key="your-api-key") as client: response = await client.midjourney.diffusion(text="...") result = await client.tasks.wait_for_completion(response.job_id) print(result.output.image_urls) asyncio.run(main()) ``` **Batch processing example:** ```python async with AsyncClient(api_key="your-api-key") as client: # Start multiple jobs responses = await asyncio.gather(*[ client.midjourney.diffusion(text=f"prompt {i}") for i in range(5) ]) # Wait for all results = await asyncio.gather(*[ client.tasks.wait_for_completion(r.job_id) for r in responses ]) ``` --- # Error Handling Handle different error types: ```python from legnext.exceptions import ( ValidationError, AuthenticationError, RateLimitError, LegnextAPIError ) try: response = client.midjourney.diffusion(text="...") except AuthenticationError: print("Invalid API key") except RateLimitError: print("Rate limited - retry later") except ValidationError as e: print(f"Invalid parameters: {e.message}") except LegnextAPIError as e: print(f"API error: {e.message}") ``` **Exception Types:** | Exception | HTTP | Description | |-----------|------|-------------| | `ValidationError` | 400 | Invalid request parameters | | `AuthenticationError` | 401 | Invalid API key | | `NotFoundError` | 404 | Resource not found | | `RateLimitError` | 429 | Rate limit exceeded | | `ServerError` | 5xx | Server error | | `LegnextAPIError` | - | Base exception | --- ## Learn More - [Image Generation API](https://docs.legnext.ai/sdk/python/image-generation) - [Video Generation API](https://docs.legnext.ai/sdk/python/video-generation) - [Quick Start](https://docs.legnext.ai/sdk/python/quickstart) --- # Installation _Install the Legnext JavaScript/Node.js SDK_ ## Install from NPM ```bash npm install @legnext/midjourney-sdk ``` ## Requirements - **Node.js**: Version 12 or higher - **Package Manager**: npm or yarn ## Supported Environments The SDK works in: - Node.js applications - Webpack-bundled projects - Browserify projects - TypeScript projects (type definitions included) ## Module Systems Supports both: - **CommonJS** - `require('@legnext/midjourney-sdk')` - **ES6 Modules** - `import { ... } from '@legnext/midjourney-sdk'` ## TypeScript Support The SDK includes full TypeScript definitions. Type declarations are automatically resolved via `package.json`. ## Verify Installation ```bash npm list @legnext/midjourney-sdk ``` --- # Authentication _Set up authentication for the Legnext JavaScript SDK_ ## Get Your API Key 1. Visit [Legnext Dashboard](https://dashboard.legnext.ai) 2. Log in to your account 3. Navigate to **API Keys** section 4. Create a new API key 5. Copy and save it securely ## Using Your API Key ### Method 1: Direct Initialization ```javascript const { Configuration, ImageApi } = require('@legnext-api/js-sdk'); const config = new Configuration({ basePath: 'https://api.legnext.ai' }); const imageApi = new ImageApi(config); const apiKey = 'your-api-key-here'; // Use apiKey as first parameter in method calls ``` **TypeScript:** ```typescript import { Configuration, ImageApi } from '@legnext-api/js-sdk'; const config = new Configuration({ basePath: 'https://api.legnext.ai' }); const imageApi = new ImageApi(config); const apiKey: string = 'your-api-key-here'; // Use apiKey as first parameter in method calls ``` ### Method 2: Environment Variable (Recommended) Set the environment variable: ```bash # macOS/Linux export LEGNEXT_API_KEY="your-api-key-here" # Windows CMD set LEGNEXT_API_KEY=your-api-key-here # Windows PowerShell $env:LEGNEXT_API_KEY="your-api-key-here" ``` Then in your code: ```javascript const apiKey = process.env.LEGNEXT_API_KEY; const imageApi = new ImageApi(apiClient); // Use apiKey in method calls ``` ### Method 3: .env File (Node.js) Create a `.env` file: ```env LEGNEXT_API_KEY=your-api-key-here LEGNEXT_BASE_URL=https://api.legnext.ai ``` Install and use dotenv: ```bash npm install dotenv ``` ```javascript require('dotenv').config(); const { Configuration, ImageApi } = require('@legnext-api/js-sdk'); const config = new Configuration({ basePath: process.env.LEGNEXT_BASE_URL || 'https://api.legnext.ai' }); const imageApi = new ImageApi(config); const apiKey = process.env.LEGNEXT_API_KEY; ``` ### Method 4: ES Modules ```javascript import 'dotenv/config'; import { Configuration, ImageApi } from '@legnext-api/js-sdk'; const config = new Configuration({ basePath: process.env.LEGNEXT_BASE_URL || 'https://api.legnext.ai' }); const imageApi = new ImageApi(config); const apiKey = process.env.LEGNEXT_API_KEY; ``` ## Security Best Practices ⚠️ **Never hardcode API keys in your code** ✅ **Always use environment variables** ✅ **Add `.env` to `.gitignore`** ✅ **Never expose API keys in client-side JavaScript** ✅ **Rotate keys regularly and revoke compromised ones** --- ## Next Steps - [Quick Start](https://docs.legnext.ai/sdk/javascript/quickstart) - [Image Generation API](https://docs.legnext.ai/sdk/javascript/image-generation) - [Video Generation API](https://docs.legnext.ai/sdk/javascript/video-generation) --- # Quick Start _Get started with the Legnext JavaScript/Node.js SDK_ ## 1. Install ```bash npm install @legnext/midjourney-sdk ``` ## 2. Set API Key Set your API key as an environment variable: ```bash export LEGNEXT_API_KEY="your-api-key" ``` ## 3. Basic Example ### JavaScript (CommonJS) ```javascript const { Configuration, ImageGenerationApi } = require('@legnext/midjourney-sdk'); const config = new Configuration({ apiKey: process.env.LEGNEXT_API_KEY, basePath: 'https://api.legnext.ai' }); const api = new ImageGenerationApi(config); // Generate image api.generateImage({ text: "a beautiful sunset over mountains" }).then(response => { console.log('Job ID:', response.data.job_id); }).catch(error => { console.error('Error:', error); }); ``` ### TypeScript (ES6) ```typescript import { Configuration, ImageGenerationApi } from '@legnext/midjourney-sdk'; const config = new Configuration({ apiKey: process.env.LEGNEXT_API_KEY!, basePath: 'https://api.legnext.ai' }); const api = new ImageGenerationApi(config); // Generate image const response = await api.generateImage({ text: "a beautiful sunset over mountains" }); console.log('Job ID:', response.data.job_id); ``` ## 4. Check Task Status ```javascript const { TaskManagementApi } = require('@legnext/midjourney-sdk'); const taskApi = new TaskManagementApi(config); // Get task status taskApi.getTaskStatus(jobId).then(response => { console.log('Status:', response.data.status); console.log('Images:', response.data.output?.image_urls); }).catch(error => { console.error('Error:', error); }); ``` ## Available APIs - `ImageGenerationApi` - Text to image, variations, upscaling, editing - `VideoGenerationApi` - Video generation and upscaling - `TaskManagementApi` - Check task status - `AccountManagementApi` - Account balance and information ## Learn More For complete API reference, see the generated `docs/` folder in the package. --- # Image Generation _Image generation API reference for JavaScript SDK_ ## apiV1DiffusionPost() Create a new text-to-image generation task. ```javascript const { Configuration, ImageApi } = require('@legnext-api/js-sdk'); const config = new Configuration({ basePath: 'https://api.legnext.ai' }); const imageApi = new ImageApi(config); const apiKey = 'your-api-key-here'; const body = { text: 'a serene mountain landscape at sunset', callback: 'https://your-domain.com/webhook' // Optional }; imageApi.apiV1DiffusionPost(apiKey, body, (error, data, response) => { if (error) { console.error('Error:', error); } else { console.log('Job ID:', data.job_id); } }); ``` **Promise-based:** ```javascript imageApi.apiV1DiffusionPost(apiKey, body) .then(response => { console.log('Job ID:', response.data.job_id); }) .catch(error => { console.error('Error:', error); }); ``` **Async/Await:** ```javascript async function generateImage() { try { const response = await imageApi.apiV1DiffusionPost(apiKey, body); console.log('Job ID:', response.data.job_id); } catch (error) { console.error('Error:', error); } } ``` **Parameters:** - `xApiKey` (String): Your API key - `body` (Object): Request body with: - `text` (String): Text prompt (1-8192 characters) - `callback` (String, optional): Webhook URL **Returns:** Promise resolving to response with `job_id` and `status` --- ## apiV1VaryPost() Create variations of a generated image. ```javascript const body = { jobId: 'original-job-id', imageNo: 0, type: 1, // 0=Subtle, 1=Strong remixPrompt: 'add more clouds' // Optional }; const response = await imageApi.apiV1VaryPost(apiKey, body); console.log('Variation Job ID:', response.jobId); ``` --- ## apiV1UpscalePost() Upscale a generated image. ```javascript const body = { jobId: 'original-job-id', imageNo: 0, type: 1 // 0=Subtle, 1=Creative }; const response = await imageApi.apiV1UpscalePost(apiKey, body); console.log('Upscale Job ID:', response.jobId); ``` --- ## apiV1RerollPost() Regenerate with the same prompt. ```javascript const body = { jobId: 'original-job-id' }; await imageApi.apiV1RerollPost(apiKey, body); ``` --- ## apiV1BlendPost() Blend 2-5 images together. ```javascript const body = { imgUrls: [ 'https://example.com/image1.png', 'https://example.com/image2.png' ], aspect_ratio: '1:1', // "2:3", "1:1", or "3:2" callback: 'https://your-domain.com/webhook' }; await imageApi.apiV1BlendPost(apiKey, body); ``` --- ## apiV1DescribePost() Generate text descriptions from an image. ```javascript const body = { imgUrl: 'https://example.com/image.png' }; await imageApi.apiV1DescribePost(apiKey, body); ``` --- ## apiV1EditPost() Edit an image by positioning it on a canvas and filling empty areas. ```javascript const body = { jobId: 'original-job-id', imageNo: 0, canvas: { width: 1024, height: 1024 }, imgPos: { width: 512, height: 512, x: 256, y: 256 }, remixPrompt: 'A beautiful landscape with mountains', callback: 'https://your-domain.com/webhook' }; await imageApi.apiV1EditPost(apiKey, body); ``` --- ## apiV1InpaintPost() Fill masked regions in an image. ```javascript const body = { jobId: 'original-job-id', imageNo: 0, mask: { areas: [ { width: 500, height: 500, points: [10, 10, 10, 100, 100, 100, 100, 10] // XYXY coordinates (clockwise) } ] }, remixPrompt: 'Add a tree in the center', // Optional callback: 'https://your-domain.com/webhook' }; await imageApi.apiV1InpaintPost(apiKey, body); ``` --- ## apiV1OutpaintPost() Extend image boundaries by scaling. ```javascript const body = { jobId: 'original-job-id', imageNo: 0, scale: 1.5, // Extension scale ratio (1.1 to 2.0) remixPrompt: 'clouds over the sky', // Optional callback: 'https://your-domain.com/webhook' }; await imageApi.apiV1OutpaintPost(apiKey, body); ``` --- ## apiV1PanPost() Create panoramic or panned views. ```javascript const body = { jobId: 'original-job-id', imageNo: 0, direction: 1, // 0=Down, 1=Right, 2=Up, 3=Left scale: 1.5, // Extension scale ratio (1.1 to 3.0) remixPrompt: 'a lake near the mountain', // Optional callback: 'https://your-domain.com/webhook' }; await imageApi.apiV1PanPost(apiKey, body); ``` --- ## apiV1RemixPost() Remix an image with a new prompt and style intensity. ```javascript const body = { jobId: 'original-job-id', imageNo: 0, remixPrompt: 'Change style to watercolor painting', mode: 0, // 0=Strong, 1=Subtle callback: 'https://your-domain.com/webhook' }; await imageApi.apiV1RemixPost(apiKey, body); ``` --- ## apiV1ShortenPost() Optimize and simplify prompts. ```javascript const body = { prompt: 'your very long and detailed prompt here...' }; const response = await imageApi.apiV1ShortenPost(apiKey, body); console.log('Optimized prompt:', response.shortenedPrompt); ``` --- ## Next Steps - [Video Generation](https://docs.legnext.ai/sdk/javascript/video-generation) - [Task Management](https://docs.legnext.ai/sdk/javascript/task-management) - [Quick Start](https://docs.legnext.ai/sdk/javascript/quickstart) --- # Video Generation _Video generation API reference for JavaScript SDK_ ## apiV1VideoDiffusionPost() Generate a video from text prompt or animate an existing image. ```javascript const { Configuration, VideoApi } = require('@legnext-api/js-sdk'); const apiClient = new Configuration(); apiClient.basePath = 'https://api.legnext.ai'; const videoApi = new VideoApi(apiClient); const apiKey = 'your-api-key-here'; // Text-to-video const body = { prompt: 'a flowing river through mountains', videoType: 1, // 0=480p (faster), 1=720p (higher quality) callback: 'https://your-domain.com/webhook' }; const response = await videoApi.apiV1VideoDiffusionPost(apiKey, body); console.log('Job ID:', response.jobId); ``` **Image-to-video animation (from generated image):** ```javascript // Animate a specific image from a generation task const body = { jobId: 'original-job-id', imageNo: 0, // Image number (0-3) prompt: 'flowing water animation', videoType: 1, callback: 'https://your-domain.com/webhook' }; const response = await videoApi.apiV1VideoDiffusionPost(apiKey, body); ``` **Image-to-video animation (from image URL):** ```javascript // Animate an existing image by URL const body = { prompt: 'https://example.com/image.png a flowing river through mountains', videoType: 1, callback: 'https://your-domain.com/webhook' }; const response = await videoApi.apiV1VideoDiffusionPost(apiKey, body); ``` **Parameters:** - `prompt` (String): Video prompt or "[image_url] prompt text" (1-8192 characters) - `videoType` (Number): Quality (0=480p, 1=720p) - `jobId` (String, optional): For animating from existing generation task - `imageNo` (Number, optional): Image number (0-3) when using jobId - `callback` (String): Webhook URL **Returns:** Promise resolving to response with `job_id` and `status` --- ## apiV1ExtendVideoPost() Extend an existing video. ```javascript const body = { jobId: 'original-video-job-id', videoNo: 0, // Video number (0-3) prompt: 'continue with dramatic lighting', // Optional callback: 'https://your-domain.com/webhook' }; const response = await videoApi.apiV1ExtendVideoPost(apiKey, body); console.log('Extended video Job ID:', response.jobId); ``` **Parameters:** - `jobId` (String): Original video task ID - `videoNo` (Number): Video number (0-3) - `prompt` (String, optional): Extension prompt (1-8192 characters) - `callback` (String): Webhook URL --- ## apiV1VideoUpscalePost() Upscale video to higher resolution. ```javascript const body = { jobId: 'original-video-job-id', videoNo: 0, // Video number (0-3) callback: 'https://your-domain.com/webhook' }; const response = await videoApi.apiV1VideoUpscalePost(apiKey, body); console.log('Upscaled video Job ID:', response.jobId); ``` **Parameters:** - `jobId` (String): Original video task ID - `videoNo` (Number): Video number (0-3) - `callback` (String): Webhook URL --- ## Complete Example ```javascript const { Configuration, VideoApi } = require('@legnext-api/js-sdk'); async function generateAndExtendVideo() { const apiClient = new Configuration(); apiClient.basePath = 'https://api.legnext.ai'; const videoApi = new VideoApi(apiClient); const apiKey = process.env.LEGNEXT_API_KEY; try { // Step 1: Generate initial video const body = { prompt: 'a sunset over ocean waves', videoType: 1 }; const initialResponse = await videoApi.apiV1VideoDiffusionPost(apiKey, body); const jobId = initialResponse.jobId; console.log('Initial video job:', jobId); // Wait for completion (see task-management.mdx) // await waitForCompletion(jobId); // Step 2: Extend the video const extendBody = { jobId: jobId, videoNo: 0, prompt: 'zoom in on the waves' }; const extendResponse = await videoApi.apiV1ExtendVideoPost(apiKey, extendBody); console.log('Extended video job:', extendResponse.jobId); } catch (error) { console.error('Error:', error); } } generateAndExtendVideo(); ``` --- ## Next Steps - [Image Generation](https://docs.legnext.ai/sdk/javascript/image-generation) - [Task Management](https://docs.legnext.ai/sdk/javascript/task-management) - [Quick Start](https://docs.legnext.ai/sdk/javascript/quickstart) --- # Task Management _Task status, polling, and error handling for JavaScript SDK_ ## apiV1JobJobIdGet() Get current task status: ```javascript const { Configuration, ImageApi } = require('@legnext-api/js-sdk'); const apiClient = new Configuration(); apiClient.basePath = 'https://api.legnext.ai'; const imageApi = new ImageApi(apiClient); const apiKey = 'your-api-key-here'; const jobId = 'job-123'; const task = await imageApi.apiV1JobJobIdGet(jobId, apiKey); console.log('Status:', task.status); console.log('Progress:', task.progress + '%'); if (task.status === 'completed') { console.log('Result:', task.output); } ``` --- ## Polling for Completion Wait for task completion with polling: ```javascript async function waitForCompletion( api, jobId, apiKey, timeoutSeconds = 300, pollIntervalSeconds = 3 ) { const startTime = Date.now(); const timeout = timeoutSeconds * 1000; while (true) { const task = await api.apiV1JobJobIdGet(jobId, apiKey); console.log('Current status:', task.status); if (task.status === 'completed') { console.log('Task completed successfully!'); console.log('Output:', task.output); return task; } else if (task.status === 'failed') { throw new Error(`Task failed: ${task.error}`); } // Check timeout if (Date.now() - startTime > timeout) { throw new Error(`Task timeout after ${timeoutSeconds} seconds`); } // Wait before next poll await new Promise(resolve => setTimeout(resolve, pollIntervalSeconds * 1000)); } } ``` **Usage:** ```javascript try { const result = await waitForCompletion(imageApi, jobId, apiKey, 300, 3); console.log('Final result:', result); } catch (error) { console.error('Error:', error.message); } ``` --- ## Complete Example with Error Handling ```javascript const { Configuration, ImageApi } = require('@legnext-api/js-sdk'); async function generateImageWithPolling() { const apiClient = new Configuration(); apiClient.basePath = 'https://api.legnext.ai'; const imageApi = new ImageApi(apiClient); const apiKey = process.env.LEGNEXT_API_KEY; try { // Step 1: Start generation const body = { text: 'a beautiful sunset over mountains' }; const response = await imageApi.apiV1DiffusionPost(apiKey, body); const jobId = response.jobId; console.log('Job started:', jobId); // Step 2: Poll for completion const result = await waitForCompletion(imageApi, jobId, apiKey, 600, 3); // Step 3: Get final result console.log('Image URLs:', result.output.imageUrls); } catch (error) { handleError(error); } } function handleError(error) { if (error.status) { const statusCode = error.status; const errorBody = error.response?.body; switch (statusCode) { case 400: console.error('Validation error:', errorBody); break; case 401: console.error('Authentication error: Invalid API key'); break; case 404: console.error('Resource not found:', errorBody); break; case 429: console.error('Rate limit exceeded. Please retry later.'); break; case 500: case 502: case 503: console.error('Server error:', errorBody); break; default: console.error(`API error (${statusCode}):`, errorBody); } } else { console.error('Unexpected error:', error.message); } } generateImageWithPolling(); ``` --- ## Error Handling **Common HTTP Status Codes:** | Status Code | Description | Action | |-------------|-------------|--------| | 400 | Invalid request parameters | Check request body format | | 401 | Invalid API key | Verify API key is correct | | 404 | Resource not found | Check job ID exists | | 429 | Rate limit exceeded | Wait and retry with backoff | | 500/502/503 | Server error | Retry with exponential backoff | **Handling Different Error Scenarios:** ```javascript async function callWithRetry(apiCall, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { try { return await apiCall(); } catch (error) { if (error.status === 429) { // Rate limited - wait and retry await new Promise(resolve => setTimeout(resolve, 5000)); continue; } else if (error.status >= 500) { // Server error - exponential backoff const delay = Math.pow(2, i) * 1000; await new Promise(resolve => setTimeout(resolve, delay)); if (i === maxRetries - 1) throw error; // Last retry continue; } else { // Other errors - don't retry throw error; } } } } // Usage try { const response = await callWithRetry(() => imageApi.apiV1DiffusionPost(apiKey, body) ); } catch (error) { console.error('Failed after retries:', error); } ``` --- ## Async Operations with Promise.all For concurrent operations: ```javascript async function generateMultipleImages() { const apiClient = new Configuration(); apiClient.basePath = 'https://api.legnext.ai'; const imageApi = new ImageApi(apiClient); const apiKey = process.env.LEGNEXT_API_KEY; const prompts = ['sunset', 'mountains', 'ocean']; try { // Start all generations concurrently const promises = prompts.map(async (prompt) => { const body = { text: prompt }; const response = await imageApi.apiV1DiffusionPost(apiKey, body); // Wait for each to complete const result = await waitForCompletion( imageApi, response.jobId, apiKey, 600, 3 ); return result.output.imageUrls[0]; }); const imageUrls = await Promise.all(promises); imageUrls.forEach((url, index) => { console.log(`Image ${index + 1}:`, url); }); } catch (error) { console.error('Error:', error); } } generateMultipleImages(); ``` --- ## Progress Callbacks ```javascript async function waitForCompletionWithProgress( api, jobId, apiKey, onProgress, timeoutSeconds = 300, pollIntervalSeconds = 3 ) { const startTime = Date.now(); const timeout = timeoutSeconds * 1000; while (true) { const task = await api.apiV1JobJobIdGet(jobId, apiKey); // Call progress callback if (onProgress) { onProgress(task.progress || 0, task.status); } if (task.status === 'completed') { return task; } else if (task.status === 'failed') { throw new Error(`Task failed: ${task.error}`); } if (Date.now() - startTime > timeout) { throw new Error(`Task timeout after ${timeoutSeconds} seconds`); } await new Promise(resolve => setTimeout(resolve, pollIntervalSeconds * 1000)); } } // Usage const result = await waitForCompletionWithProgress( imageApi, jobId, apiKey, (progress, status) => { console.log(`Progress: ${progress}% - Status: ${status}`); } ); ``` --- ## Learn More - [Image Generation API](https://docs.legnext.ai/sdk/javascript/image-generation) - [Video Generation API](https://docs.legnext.ai/sdk/javascript/video-generation) - [Quick Start](https://docs.legnext.ai/sdk/javascript/quickstart) --- # Installation _Install the Legnext Go SDK_ ## Install Package ```bash go get github.com/legnext-ai/sdks/sdks/go ``` ## Requirements - **Go**: Version 1.16 or higher ## Dependencies The SDK requires these dependencies: ```bash go get github.com/stretchr/testify/assert go get golang.org/x/net/context ``` ## Import Package ```go import legnext "github.com/legnext-ai/sdks/sdks/go" ``` ## Verify Installation ```bash go list -m github.com/legnext-ai/sdks/sdks/go ``` --- # Authentication _Set up API authentication for Go SDK_ ## Getting Your API Key 1. Visit [Legnext.ai Dashboard](https://legnext.ai/dashboard) 2. Navigate to API Keys section 3. Generate a new API key 4. Copy and store securely ## Authentication Methods ### Method 1: Environment Variables (Recommended) Set your API key as an environment variable: ```bash export LEGNEXT_API_KEY="your-api-key-here" ``` Then use it in your Go code: ```go package main import ( "context" "fmt" "os" legnext "github.com/legnext-ai/sdks/sdks/go" ) func main() { // Configure API client config := legnext.NewConfiguration() config.Servers = legnext.ServerConfigurations{ { URL: "https://api.legnext.ai", }, } // Add API key from environment variable apiKey := os.Getenv("LEGNEXT_API_KEY") config.AddDefaultHeader("x-api-key", apiKey) client := legnext.NewAPIClient(config) ctx := context.Background() // Now you can use the client // ... } ``` ### Method 2: Direct Initialization Hardcode the API key directly (not recommended for production): ```go package main import ( "context" legnext "github.com/legnext-ai/sdks/sdks/go" ) func main() { config := legnext.NewConfiguration() config.Servers = legnext.ServerConfigurations{ { URL: "https://api.legnext.ai", }, } // Add API key directly config.AddDefaultHeader("x-api-key", "your-api-key-here") client := legnext.NewAPIClient(config) ctx := context.Background() // Use the client // ... } ``` ### Method 3: Configuration File Load API key from a configuration file: ```go package main import ( "context" "encoding/json" "fmt" "os" legnext "github.com/legnext-ai/sdks/sdks/go" ) type Config struct { APIKey string `json:"api_key"` } func loadConfig(path string) (*Config, error) { file, err := os.Open(path) if err != nil { return nil, err } defer file.Close() var config Config decoder := json.NewDecoder(file) err = decoder.Decode(&config) if err != nil { return nil, err } return &config, nil } func main() { // Load configuration cfg, err := loadConfig("config.json") if err != nil { fmt.Printf("Error loading config: %v\n", err) return } // Configure API client config := legnext.NewConfiguration() config.Servers = legnext.ServerConfigurations{ { URL: "https://api.legnext.ai", }, } config.AddDefaultHeader("x-api-key", cfg.APIKey) client := legnext.NewAPIClient(config) ctx := context.Background() // Use the client // ... } ``` **config.json:** ```json { "api_key": "your-api-key-here" } ``` ### Method 4: Using godotenv Use the `godotenv` package to load from `.env` files: ```bash go get github.com/joho/godotenv ``` ```go package main import ( "context" "fmt" "log" "os" legnext "github.com/legnext-ai/sdks/sdks/go" "github.com/joho/godotenv" ) func main() { // Load .env file err := godotenv.Load() if err != nil { log.Fatal("Error loading .env file") } // Configure API client config := legnext.NewConfiguration() config.Servers = legnext.ServerConfigurations{ { URL: "https://api.legnext.ai", }, } apiKey := os.Getenv("LEGNEXT_API_KEY") if apiKey == "" { log.Fatal("LEGNEXT_API_KEY not set") } config.AddDefaultHeader("x-api-key", apiKey) client := legnext.NewAPIClient(config) ctx := context.Background() // Use the client // ... } ``` **.env file:** ``` LEGNEXT_API_KEY=your-api-key-here ``` --- ## Security Best Practices 1. **Never commit API keys to version control** - Add `.env` and `config.json` to `.gitignore` - Use environment variables in production 2. **Use environment variables in production** ```bash # Set in your deployment environment export LEGNEXT_API_KEY="your-production-key" ``` 3. **Rotate keys regularly** - Generate new keys periodically - Revoke old keys after rotation 4. **Use different keys for development and production** ```go var apiKey string if os.Getenv("ENVIRONMENT") == "production" { apiKey = os.Getenv("LEGNEXT_PROD_API_KEY") } else { apiKey = os.Getenv("LEGNEXT_DEV_API_KEY") } ``` 5. **Restrict API key permissions** - Use the minimum required permissions - Monitor usage through the dashboard --- ## Testing Authentication Verify your API key is working: ```go package main import ( "context" "fmt" "os" legnext "github.com/legnext-ai/sdks/sdks/go" ) func main() { config := legnext.NewConfiguration() config.Servers = legnext.ServerConfigurations{ { URL: "https://api.legnext.ai", }, } apiKey := os.Getenv("LEGNEXT_API_KEY") config.AddDefaultHeader("x-api-key", apiKey) client := legnext.NewAPIClient(config) ctx := context.Background() // Test with account balance endpoint balance, httpRes, err := client.AccountManagementAPI.ApiAccountBalanceGet(ctx).XApiKey(apiKey).Execute() if err != nil { if httpRes != nil && httpRes.StatusCode == 401 { fmt.Println("❌ Authentication failed: Invalid API key") } else { fmt.Printf("❌ Error: %v\n", err) } return } fmt.Println("✅ Authentication successful!") if balance.Data != nil { fmt.Printf("Balance: $%.2f\n", *balance.Data.BalanceUsd) } } ``` --- ## Next Steps - [Image Generation](https://docs.legnext.ai/sdk/go/image-generation) - [Video Generation](https://docs.legnext.ai/sdk/go/video-generation) - [Task Management](https://docs.legnext.ai/sdk/go/task-management) - [Quick Start](https://docs.legnext.ai/sdk/go/quickstart) --- # Quick Start _Get started with the Legnext Go SDK_ ## 1. Install ```bash go get github.com/legnext-ai/sdks/sdks/go ``` ## 2. Set API Key Set your API key as an environment variable: ```bash export LEGNEXT_API_KEY="your-api-key" ``` ## 3. Basic Example ```go package main import ( "context" "fmt" "os" legnext "github.com/legnext-ai/sdks/sdks/go" ) func main() { // Configure API client config := legnext.NewConfiguration() config.Servers = legnext.ServerConfigurations{ { URL: "https://api.legnext.ai", }, } config.AddDefaultHeader("x-api-key", os.Getenv("LEGNEXT_API_KEY")) client := legnext.NewAPIClient(config) ctx := context.Background() // Generate image request := legnext.DiffusionRequest{ Text: "a beautiful sunset over mountains", } response, httpRes, err := client.ImageGenerationAPI.GenerateImage(ctx). DiffusionRequest(request). Execute() if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Job ID: %s\n", *response.JobId) fmt.Printf("Status: %s\n", *response.Status) } ``` ## 4. Check Task Status ```go // Get task status taskResponse, httpRes, err := client.VideoAPI.ApiV1JobJobIdGet(ctx, jobId).Execute() if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Status: %s\n", *taskResponse.Status) if taskResponse.Output != nil && taskResponse.Output.ImageUrls != nil { fmt.Printf("Images: %v\n", taskResponse.Output.ImageUrls) } ``` ## Error Handling ```go response, httpRes, err := client.ImageGenerationAPI.GenerateImage(ctx). DiffusionRequest(request). Execute() if err != nil { // Check HTTP status code if httpRes != nil { fmt.Printf("HTTP Status: %d\n", httpRes.StatusCode) } fmt.Printf("Error: %v\n", err) return } ``` ## Available APIs - `ImageGenerationAPI` - Text to image, variations, upscaling, editing - `VideoGenerationAPI` - Video generation and upscaling - `VideoAPI` - Task status checking - `AccountManagementAPI` - Account balance and information --- # Image Generation _Image generation API reference for Go SDK_ ## GenerateImage() Create a new text-to-image generation task. ```go package main import ( "context" "fmt" "os" legnext "github.com/legnext-ai/sdks/sdks/go" ) func main() { config := legnext.NewConfiguration() config.Servers = legnext.ServerConfigurations{ { URL: "https://api.legnext.ai", }, } apiKey := os.Getenv("LEGNEXT_API_KEY") config.AddDefaultHeader("x-api-key", apiKey) client := legnext.NewAPIClient(config) ctx := context.Background() // Create image generation request text := "a serene mountain landscape at sunset" callback := "https://your-domain.com/webhook" request := legnext.DiffusionRequest{ Text: &text, Callback: &callback, } response, httpRes, err := client.ImageGenerationAPI.GenerateImage(ctx). DiffusionRequest(request). Execute() if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Job ID: %s\n", *response.JobId) fmt.Printf("Status: %s\n", *response.Status) } ``` **Parameters:** - `Text` (string): Text prompt (1-8192 characters) - `Callback` (string, optional): Webhook URL for completion notification **Returns:** Response with `JobId` and `Status` --- ## VaryImage() Create variations of a generated image. ```go jobId := "original-job-id" imageNo := int32(0) varyType := int32(1) // 0=Subtle, 1=Strong remixPrompt := "add more clouds" callback := "https://your-domain.com/webhook" request := legnext.VaryRequest{ JobId: &jobId, ImageNo: &imageNo, Type: &varyType, RemixPrompt: &remixPrompt, Callback: &callback, } response, httpRes, err := client.ImageGenerationAPI.VaryImage(ctx). VaryRequest(request). Execute() if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Variation Job ID: %s\n", *response.JobId) ``` **Parameters:** - `JobId` (string): Original image job ID - `ImageNo` (int32): Image index (0-3) - `Type` (int32): Variation type (0=Subtle, 1=Strong) - `RemixPrompt` (string, optional): Additional prompt for variation - `Callback` (string, optional): Webhook URL --- ## RemixImage() Transform an image with a new prompt. ```go jobId := "original-job-id" imageNo := int32(0) remixPrompt := "transform into a dramatic storm scene" mode := int32(0) // 0=Strong, 1=Subtle callback := "https://your-domain.com/webhook" request := legnext.RemixRequest{ JobId: &jobId, ImageNo: &imageNo, RemixPrompt: &remixPrompt, Mode: &mode, Callback: &callback, } response, httpRes, err := client.ImageGenerationAPI.RemixImage(ctx). RemixRequest(request). Execute() if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Remix Job ID: %s\n", *response.JobId) ``` **Parameters:** - `JobId` (string): Original image job ID - `ImageNo` (int32): Image index (0-3) - `RemixPrompt` (string): New prompt to apply to the image - `Mode` (int32): Remix intensity (0=Strong, 1=Subtle) - `Callback` (string, optional): Webhook URL --- ## UpscaleImage() Upscale a generated image to higher resolution. ```go jobId := "original-job-id" imageNo := int32(0) upscaleType := int32(1) // 0=Subtle, 1=Creative callback := "https://your-domain.com/webhook" request := legnext.UpscaleRequest{ JobId: &jobId, ImageNo: &imageNo, Type: &upscaleType, Callback: &callback, } response, httpRes, err := client.ImageGenerationAPI.UpscaleImage(ctx). UpscaleRequest(request). Execute() if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Upscale Job ID: %s\n", *response.JobId) ``` **Parameters:** - `JobId` (string): Original image job ID - `ImageNo` (int32): Image index (0-3) - `Type` (int32): Upscale type (0=Subtle, 1=Creative) - `Callback` (string, optional): Webhook URL --- ## RerollImage() Regenerate with the same prompt. ```go jobId := "original-job-id" callback := "https://your-domain.com/webhook" request := legnext.RerollRequest{ JobId: &jobId, Callback: &callback, } response, httpRes, err := client.ImageGenerationAPI.RerollImage(ctx). RerollRequest(request). Execute() if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Reroll Job ID: %s\n", *response.JobId) ``` **Parameters:** - `JobId` (string): Original image job ID - `Callback` (string, optional): Webhook URL --- ## BlendImages() Blend 2-5 images together. ```go imageUrls := []string{ "https://example.com/image1.png", "https://example.com/image2.png", } aspectRatio := "1:1" // Options: 1:1, 16:9, 9:16, 3:2, 2:3 callback := "https://your-domain.com/webhook" request := legnext.BlendRequest{ ImgUrls: imageUrls, AspectRatio: &aspectRatio, Callback: &callback, } response, httpRes, err := client.ImageGenerationAPI.BlendImages(ctx). BlendRequest(request). Execute() if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Blend Job ID: %s\n", *response.JobId) ``` **Parameters:** - `ImgUrls` ([]string): Array of 2-5 image URLs - `AspectRatio` (string, optional): Output aspect ratio (1:1, 16:9, 9:16, 3:2, 2:3) - `Callback` (string, optional): Webhook URL --- ## DescribeImage() Generate text descriptions from an image. ```go imgUrl := "https://example.com/image.png" callback := "https://your-domain.com/webhook" request := legnext.DescribeRequest{ ImgUrl: &imgUrl, Callback: &callback, } response, httpRes, err := client.ImageGenerationAPI.DescribeImage(ctx). DescribeRequest(request). Execute() if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Describe Job ID: %s\n", *response.JobId) ``` **Parameters:** - `ImgUrl` (string): URL of the image to describe - `Callback` (string, optional): Webhook URL --- ## EditImage() Edit an image with text description. ```go jobId := "original-job-id" imageNo := int32(0) canvas := "1:1" // Canvas size imgPos := int32(0) // Image position remixPrompt := "change the sky to sunset colors" callback := "https://your-domain.com/webhook" request := legnext.EditRequest{ JobId: &jobId, ImageNo: &imageNo, Canvas: &canvas, ImgPos: &imgPos, RemixPrompt: &remixPrompt, Callback: &callback, } response, httpRes, err := client.ImageGenerationAPI.EditImage(ctx). EditRequest(request). Execute() if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Edit Job ID: %s\n", *response.JobId) ``` **Parameters:** - `JobId` (string): Original image job ID - `ImageNo` (int32): Image index (0-3) - `Canvas` (string): Canvas size (e.g., "1:1") - `ImgPos` (int32): Image position - `RemixPrompt` (string): Edit instructions - `Callback` (string, optional): Webhook URL --- ## InpaintImage() Fill masked regions in an image. ```go jobId := "original-job-id" imageNo := int32(0) remixPrompt := "fill with forest landscape" mask := "mask-url-or-coordinates" callback := "https://your-domain.com/webhook" request := legnext.InpaintRequest{ JobId: &jobId, ImageNo: &imageNo, RemixPrompt: &remixPrompt, Mask: &mask, Callback: &callback, } response, httpRes, err := client.ImageGenerationAPI.InpaintImage(ctx). InpaintRequest(request). Execute() if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Inpaint Job ID: %s\n", *response.JobId) ``` **Parameters:** - `JobId` (string): Original image job ID - `ImageNo` (int32): Image index (0-3) - `RemixPrompt` (string): Inpainting prompt - `Mask` (string): Mask data or coordinates - `Callback` (string, optional): Webhook URL --- ## OutpaintImage() Extend image boundaries. ```go jobId := "original-job-id" imageNo := int32(0) scale := float32(1.5) // Scale factor (1.1-3.0) remixPrompt := "extend with matching scenery" callback := "https://your-domain.com/webhook" request := legnext.OutpaintRequest{ JobId: &jobId, ImageNo: &imageNo, Scale: &scale, RemixPrompt: &remixPrompt, Callback: &callback, } response, httpRes, err := client.ImageGenerationAPI.OutpaintImage(ctx). OutpaintRequest(request). Execute() if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Outpaint Job ID: %s\n", *response.JobId) ``` **Parameters:** - `JobId` (string): Original image job ID - `ImageNo` (int32): Image index (0-3) - `Scale` (float32): Scale factor (1.1-3.0) - `RemixPrompt` (string, optional): Outpainting prompt - `Callback` (string, optional): Webhook URL --- ## PanImage() Create panoramic or panned views. ```go jobId := "original-job-id" imageNo := int32(0) direction := int32(1) // 0=Down, 1=Right, 2=Up, 3=Left scale := float32(1.5) // Scale factor (1.1-3.0) remixPrompt := "pan to the right with continuous scenery" callback := "https://your-domain.com/webhook" request := legnext.PanRequest{ JobId: &jobId, ImageNo: &imageNo, Direction: &direction, Scale: &scale, RemixPrompt: &remixPrompt, Callback: &callback, } response, httpRes, err := client.ImageGenerationAPI.PanImage(ctx). PanRequest(request). Execute() if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Pan Job ID: %s\n", *response.JobId) ``` **Parameters:** - `JobId` (string): Original image job ID - `ImageNo` (int32): Image index (0-3) - `Direction` (int32): Pan direction (0=Down, 1=Right, 2=Up, 3=Left) - `Scale` (float32): Scale factor (1.1-3.0) - `RemixPrompt` (string, optional): Panning prompt - `Callback` (string, optional): Webhook URL --- ## ShortenPrompt() Optimize and simplify prompts. ```go prompt := "your very long and detailed prompt here with lots of unnecessary words and descriptions that could be made more concise..." request := legnext.ShortenRequest{ Prompt: &prompt, } response, httpRes, err := client.ImageGenerationAPI.ShortenPrompt(ctx). ShortenRequest(request). Execute() if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Shortened prompt: %s\n", *response.ShortenedPrompt) ``` **Parameters:** - `Prompt` (string): Long prompt to optimize **Returns:** Response with `ShortenedPrompt` --- ## Complete Example ```go package main import ( "context" "fmt" "os" legnext "github.com/legnext-ai/sdks/sdks/go" ) func main() { // Configure API client config := legnext.NewConfiguration() config.Servers = legnext.ServerConfigurations{ { URL: "https://api.legnext.ai", }, } apiKey := os.Getenv("LEGNEXT_API_KEY") config.AddDefaultHeader("x-api-key", apiKey) client := legnext.NewAPIClient(config) ctx := context.Background() // Step 1: Generate image text := "a beautiful sunset over mountains" callback := "https://your-domain.com/webhook" request := legnext.DiffusionRequest{ Text: &text, Callback: &callback, } response, _, err := client.ImageGenerationAPI.GenerateImage(ctx). DiffusionRequest(request). Execute() if err != nil { fmt.Printf("Error: %v\n", err) return } jobId := *response.JobId fmt.Printf("Image generation started: %s\n", jobId) // Step 2: Wait for completion (see Task Management docs) // ... // Step 3: Upscale the first image imageNo := int32(0) upscaleType := int32(1) upscaleRequest := legnext.UpscaleRequest{ JobId: &jobId, ImageNo: &imageNo, Type: &upscaleType, } upscaleResponse, _, err := client.ImageGenerationAPI.UpscaleImage(ctx). UpscaleRequest(upscaleRequest). Execute() if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Upscale started: %s\n", *upscaleResponse.JobId) } ``` --- ## Next Steps - [Video Generation](https://docs.legnext.ai/sdk/go/video-generation) - [Task Management](https://docs.legnext.ai/sdk/go/task-management) - [Quick Start](https://docs.legnext.ai/sdk/go/quickstart) --- # Video Generation _Video generation API reference for Go SDK_ ## GenerateVideo() Generate a video from text prompt, image URL, or existing generated image. ```go package main import ( "context" "fmt" "os" legnext "github.com/legnext-ai/sdks/sdks/go" ) func main() { config := legnext.NewConfiguration() config.Servers = legnext.ServerConfigurations{ { URL: "https://api.legnext.ai", }, } apiKey := os.Getenv("LEGNEXT_API_KEY") config.AddDefaultHeader("x-api-key", apiKey) client := legnext.NewAPIClient(config) ctx := context.Background() // Option 1: Generate from text only prompt := "a flowing river through mountains" videoType := int32(1) // 0=480p, 1=720p callback := "https://your-domain.com/webhook" request := legnext.VideoDiffusionRequest{ Prompt: &prompt, VideoType: &videoType, Callback: &callback, } response, httpRes, err := client.VideoGenerationAPI.GenerateVideo(ctx). VideoDiffusionRequest(request). Execute() if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Job ID: %s\n", *response.JobId) fmt.Printf("Status: %s\n", *response.Status) } ``` **Option 2: Generate from Image URL:** ```go // Generate from image URL prompt := "https://example.com/image.png a flowing river through mountains" videoType := int32(1) callback := "https://your-domain.com/webhook" request := legnext.VideoDiffusionRequest{ Prompt: &prompt, VideoType: &videoType, Callback: &callback, } response, httpRes, err := client.VideoGenerationAPI.GenerateVideo(ctx). VideoDiffusionRequest(request). Execute() if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Job ID: %s\n", *response.JobId) ``` **Option 3: Animate Generated Image:** ```go // Animate from previously generated image originalJobId := "image-generation-job-id" imageNo := int32(0) videoType := int32(1) callback := "https://your-domain.com/webhook" request := legnext.VideoDiffusionRequest{ JobId: &originalJobId, ImageNo: &imageNo, VideoType: &videoType, Callback: &callback, } response, httpRes, err := client.VideoGenerationAPI.GenerateVideo(ctx). VideoDiffusionRequest(request). Execute() if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Job ID: %s\n", *response.JobId) ``` **Parameters:** - `Prompt` (string, conditional): Video prompt or "[image_url] prompt text" (1-8192 characters) - required for text/URL mode - `JobId` (string, conditional): Original image generation job ID - required for image animation mode - `ImageNo` (int32, conditional): Image index (0-3) - required when using JobId - `VideoType` (int32, optional): Quality (0=480p, 1=720p) - `Callback` (string, optional): Webhook URL **Returns:** Response with `JobId` and `Status` --- ## ExtendVideo() Extend an existing video. ```go jobId := "original-video-job-id" videoNo := int32(0) prompt := "continue with dramatic lighting" callback := "https://your-domain.com/webhook" request := legnext.ExtendVideoRequest{ JobId: &jobId, VideoNo: &videoNo, Prompt: &prompt, Callback: &callback, } response, httpRes, err := client.VideoGenerationAPI.ExtendVideo(ctx). ExtendVideoRequest(request). Execute() if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Extension Job ID: %s\n", *response.JobId) ``` **Parameters:** - `JobId` (string): Original video task ID - `VideoNo` (int32): Video index (0-3) - `Prompt` (string, optional): Extension prompt (1-8192 characters) - `Callback` (string, optional): Webhook URL **Returns:** Response with `JobId` and `Status` --- ## UpscaleVideo() Upscale video to higher resolution. ```go jobId := "original-video-job-id" videoNo := int32(0) callback := "https://your-domain.com/webhook" request := legnext.VideoUpscaleRequest{ JobId: &jobId, VideoNo: &videoNo, Callback: &callback, } response, httpRes, err := client.VideoGenerationAPI.UpscaleVideo(ctx). VideoUpscaleRequest(request). Execute() if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Upscale Job ID: %s\n", *response.JobId) ``` **Parameters:** - `JobId` (string): Original video task ID - `VideoNo` (int32): Video index (0-3) - `Callback` (string, optional): Webhook URL **Returns:** Response with `JobId` and `Status` --- ## Complete Example ```go package main import ( "context" "fmt" "os" legnext "github.com/legnext-ai/sdks/sdks/go" ) func main() { // Configure API client config := legnext.NewConfiguration() config.Servers = legnext.ServerConfigurations{ { URL: "https://api.legnext.ai", }, } apiKey := os.Getenv("LEGNEXT_API_KEY") if apiKey == "" { fmt.Println("LEGNEXT_API_KEY environment variable not set") return } config.AddDefaultHeader("x-api-key", apiKey) client := legnext.NewAPIClient(config) ctx := context.Background() // Step 1: Generate video prompt := "a beautiful sunset over the ocean" videoType := int32(1) request := legnext.VideoDiffusionRequest{ Prompt: &prompt, VideoType: &videoType, } response, _, err := client.VideoGenerationAPI.GenerateVideo(ctx). VideoDiffusionRequest(request). Execute() if err != nil { fmt.Printf("Error generating video: %v\n", err) return } jobId := *response.JobId fmt.Printf("Video generation started: %s\n", jobId) // Step 2: Wait for completion (see Task Management docs) // ... // Step 3: Extend the video videoNo := int32(0) extendPrompt := "continue with dramatic clouds" extendRequest := legnext.ExtendVideoRequest{ JobId: &jobId, VideoNo: &videoNo, Prompt: &extendPrompt, } extendResponse, _, err := client.VideoGenerationAPI.ExtendVideo(ctx). ExtendVideoRequest(extendRequest). Execute() if err != nil { fmt.Printf("Error extending video: %v\n", err) return } fmt.Printf("Video extension started: %s\n", *extendResponse.JobId) // Step 4: Upscale the extended video upscaleRequest := legnext.VideoUpscaleRequest{ JobId: extendResponse.JobId, VideoNo: &videoNo, } upscaleResponse, _, err := client.VideoGenerationAPI.UpscaleVideo(ctx). VideoUpscaleRequest(upscaleRequest). Execute() if err != nil { fmt.Printf("Error upscaling video: %v\n", err) return } fmt.Printf("Video upscale started: %s\n", *upscaleResponse.JobId) } ``` --- ## Error Handling ```go response, httpRes, err := client.VideoGenerationAPI.GenerateVideo(ctx). VideoDiffusionRequest(request). Execute() if err != nil { if httpRes != nil { switch httpRes.StatusCode { case 400: fmt.Println("Validation error: Check request parameters") case 401: fmt.Println("Authentication error: Invalid API key") case 404: fmt.Println("Resource not found") case 429: fmt.Println("Rate limit exceeded. Please retry later.") case 500, 502, 503: fmt.Println("Server error. Please retry.") default: fmt.Printf("API error (%d): %v\n", httpRes.StatusCode, err) } } else { fmt.Printf("Unexpected error: %v\n", err) } return } ``` --- ## Next Steps - [Image Generation](https://docs.legnext.ai/sdk/go/image-generation) - [Task Management](https://docs.legnext.ai/sdk/go/task-management) - [Quick Start](https://docs.legnext.ai/sdk/go/quickstart) --- # Task Management _Task status, polling, and error handling for Go SDK_ ## GetTaskStatus() Get current task status: ```go package main import ( "context" "fmt" "os" legnext "github.com/legnext-ai/sdks/sdks/go" ) func main() { config := legnext.NewConfiguration() config.Servers = legnext.ServerConfigurations{ { URL: "https://api.legnext.ai", }, } apiKey := os.Getenv("LEGNEXT_API_KEY") config.AddDefaultHeader("x-api-key", apiKey) client := legnext.NewAPIClient(config) ctx := context.Background() jobId := "job-123" task, httpRes, err := client.TaskManagementAPI.GetTaskStatus(ctx, jobId).Execute() if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Status: %s\n", *task.Status) fmt.Printf("Progress: %d%%\n", *task.Progress) if *task.Status == "completed" { fmt.Printf("Result: %v\n", task.Output) } } ``` --- ## Polling for Completion Wait for task completion with polling: ```go package main import ( "context" "fmt" "os" "time" legnext "github.com/legnext-ai/sdks/sdks/go" ) func waitForCompletion( ctx context.Context, client *legnext.APIClient, jobId string, timeoutSeconds int, pollIntervalSeconds int, ) (*legnext.TaskResponse, error) { startTime := time.Now() timeout := time.Duration(timeoutSeconds) * time.Second for { task, _, err := client.TaskManagementAPI.GetTaskStatus(ctx, jobId).Execute() if err != nil { return nil, err } fmt.Printf("Current status: %s\n", *task.Status) if *task.Status == "completed" { fmt.Println("Task completed successfully!") fmt.Printf("Output: %v\n", task.Output) return task, nil } else if *task.Status == "failed" { return nil, fmt.Errorf("task failed: %v", task.Error) } // Check timeout if time.Since(startTime) > timeout { return nil, fmt.Errorf("task timeout after %d seconds", timeoutSeconds) } // Wait before next poll time.Sleep(time.Duration(pollIntervalSeconds) * time.Second) } } func main() { config := legnext.NewConfiguration() config.Servers = legnext.ServerConfigurations{ { URL: "https://api.legnext.ai", }, } apiKey := os.Getenv("LEGNEXT_API_KEY") config.AddDefaultHeader("x-api-key", apiKey) client := legnext.NewAPIClient(config) ctx := context.Background() jobId := "job-123" result, err := waitForCompletion(ctx, client, jobId, 300, 3) if err != nil { fmt.Printf("Error: %v\n", err) return } fmt.Printf("Final result: %v\n", result) } ``` --- ## Complete Example with Error Handling ```go package main import ( "context" "fmt" "os" "time" legnext "github.com/legnext-ai/sdks/sdks/go" ) func waitForCompletion( ctx context.Context, client *legnext.APIClient, jobId string, timeoutSeconds int, pollIntervalSeconds int, ) (*legnext.TaskResponse, error) { startTime := time.Now() timeout := time.Duration(timeoutSeconds) * time.Second for { task, _, err := client.TaskManagementAPI.GetTaskStatus(ctx, jobId).Execute() if err != nil { return nil, err } if *task.Status == "completed" { return task, nil } else if *task.Status == "failed" { return nil, fmt.Errorf("task failed: %v", task.Error) } if time.Since(startTime) > timeout { return nil, fmt.Errorf("task timeout after %d seconds", timeoutSeconds) } time.Sleep(time.Duration(pollIntervalSeconds) * time.Second) } } func generateImageWithPolling() error { config := legnext.NewConfiguration() config.Servers = legnext.ServerConfigurations{ { URL: "https://api.legnext.ai", }, } apiKey := os.Getenv("LEGNEXT_API_KEY") config.AddDefaultHeader("x-api-key", apiKey) client := legnext.NewAPIClient(config) ctx := context.Background() // Step 1: Start generation text := "a beautiful sunset over mountains" request := legnext.DiffusionRequest{ Text: &text, } response, _, err := client.ImageGenerationAPI.GenerateImage(ctx). DiffusionRequest(request). Execute() if err != nil { return fmt.Errorf("error starting generation: %v", err) } jobId := *response.JobId fmt.Printf("Job started: %s\n", jobId) // Step 2: Poll for completion result, err := waitForCompletion(ctx, client, jobId, 600, 3) if err != nil { return fmt.Errorf("error waiting for completion: %v", err) } // Step 3: Get final result if result.Output != nil && result.Output.ImageUrls != nil { fmt.Printf("Image URLs: %v\n", result.Output.ImageUrls) } return nil } func main() { if err := generateImageWithPolling(); err != nil { fmt.Printf("Error: %v\n", err) } } ``` --- ## Error Handling **HTTP Error Handling:** ```go task, httpRes, err := client.TaskManagementAPI.GetTaskStatus(ctx, jobId).Execute() if err != nil { if httpRes != nil { switch httpRes.StatusCode { case 400: fmt.Println("Validation error: Check request parameters") case 401: fmt.Println("Authentication error: Invalid API key") case 404: fmt.Println("Resource not found: Check job ID exists") case 429: fmt.Println("Rate limit exceeded. Please retry later.") case 500, 502, 503: fmt.Println("Server error. Please retry with backoff.") default: fmt.Printf("API error (%d): %v\n", httpRes.StatusCode, err) } } else { fmt.Printf("Unexpected error: %v\n", err) } return } ``` **Common HTTP Status Codes:** | Status Code | Description | Action | |-------------|-------------|--------| | 400 | Invalid request parameters | Check request body format | | 401 | Invalid API key | Verify API key is correct | | 404 | Resource not found | Check job ID exists | | 429 | Rate limit exceeded | Wait and retry with backoff | | 500/502/503 | Server error | Retry with exponential backoff | **Retry Logic with Exponential Backoff:** ```go import ( "math" "time" ) func callWithRetry( ctx context.Context, client *legnext.APIClient, request legnext.DiffusionRequest, maxRetries int, ) (*legnext.TaskResponse, error) { for i := 0; i < maxRetries; i++ { response, httpRes, err := client.ImageGenerationAPI.GenerateImage(ctx). DiffusionRequest(request). Execute() if err != nil { if httpRes != nil { if httpRes.StatusCode == 429 { // Rate limited - wait and retry time.Sleep(5 * time.Second) continue } else if httpRes.StatusCode >= 500 { // Server error - exponential backoff delay := time.Duration(math.Pow(2, float64(i))) * time.Second time.Sleep(delay) if i == maxRetries-1 { return nil, err } continue } else { // Other errors - don't retry return nil, err } } return nil, err } return response, nil } return nil, fmt.Errorf("max retries exceeded") } // Usage text := "a beautiful landscape" request := legnext.DiffusionRequest{ Text: &text, } response, err := callWithRetry(ctx, client, request, 3) if err != nil { fmt.Printf("Failed after retries: %v\n", err) return } ``` --- ## Concurrent Operations with Goroutines For processing multiple tasks concurrently: ```go package main import ( "context" "fmt" "os" "sync" legnext "github.com/legnext-ai/sdks/sdks/go" ) func generateMultipleImages() error { config := legnext.NewConfiguration() config.Servers = legnext.ServerConfigurations{ { URL: "https://api.legnext.ai", }, } apiKey := os.Getenv("LEGNEXT_API_KEY") config.AddDefaultHeader("x-api-key", apiKey) client := legnext.NewAPIClient(config) ctx := context.Background() prompts := []string{"sunset", "mountains", "ocean"} var wg sync.WaitGroup results := make(chan string, len(prompts)) errors := make(chan error, len(prompts)) for _, prompt := range prompts { wg.Add(1) go func(p string) { defer wg.Done() // Start generation text := p request := legnext.DiffusionRequest{ Text: &text, } response, _, err := client.ImageGenerationAPI.GenerateImage(ctx). DiffusionRequest(request). Execute() if err != nil { errors <- err return } jobId := *response.JobId // Wait for completion result, err := waitForCompletion(ctx, client, jobId, 600, 3) if err != nil { errors <- err return } if result.Output != nil && result.Output.ImageUrls != nil && len(result.Output.ImageUrls) > 0 { results <- result.Output.ImageUrls[0] } }(prompt) } // Wait for all goroutines go func() { wg.Wait() close(results) close(errors) }() // Collect results for { select { case url, ok := <-results: if ok { fmt.Printf("Image generated: %s\n", url) } case err, ok := <-errors: if ok { fmt.Printf("Error: %v\n", err) } } if len(results) == 0 && len(errors) == 0 { break } } return nil } func main() { if err := generateMultipleImages(); err != nil { fmt.Printf("Error: %v\n", err) } } ``` --- ## Progress Callbacks ```go type ProgressCallback func(progress int, status string) func waitForCompletionWithProgress( ctx context.Context, client *legnext.APIClient, jobId string, onProgress ProgressCallback, timeoutSeconds int, pollIntervalSeconds int, ) (*legnext.TaskResponse, error) { startTime := time.Now() timeout := time.Duration(timeoutSeconds) * time.Second for { task, _, err := client.TaskManagementAPI.GetTaskStatus(ctx, jobId).Execute() if err != nil { return nil, err } // Call progress callback if onProgress != nil { progress := 0 if task.Progress != nil { progress = int(*task.Progress) } status := "" if task.Status != nil { status = *task.Status } onProgress(progress, status) } if *task.Status == "completed" { return task, nil } else if *task.Status == "failed" { return nil, fmt.Errorf("task failed: %v", task.Error) } if time.Since(startTime) > timeout { return nil, fmt.Errorf("task timeout after %d seconds", timeoutSeconds) } time.Sleep(time.Duration(pollIntervalSeconds) * time.Second) } } // Usage result, err := waitForCompletionWithProgress( ctx, client, jobId, func(progress int, status string) { fmt.Printf("Progress: %d%% - Status: %s\n", progress, status) }, 600, 3, ) ``` --- ## Context with Timeout Use Go's context for better timeout management: ```go import ( "context" "time" ) func main() { // Create context with timeout ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) defer cancel() config := legnext.NewConfiguration() config.Servers = legnext.ServerConfigurations{ { URL: "https://api.legnext.ai", }, } apiKey := os.Getenv("LEGNEXT_API_KEY") config.AddDefaultHeader("x-api-key", apiKey) client := legnext.NewAPIClient(config) // Start generation text := "a beautiful landscape" request := legnext.DiffusionRequest{ Text: &text, } response, _, err := client.ImageGenerationAPI.GenerateImage(ctx). DiffusionRequest(request). Execute() if err != nil { if ctx.Err() == context.DeadlineExceeded { fmt.Println("Request timeout exceeded") } else { fmt.Printf("Error: %v\n", err) } return } fmt.Printf("Job ID: %s\n", *response.JobId) } ``` --- ## Learn More - [Image Generation API](https://docs.legnext.ai/sdk/go/image-generation) - [Video Generation API](https://docs.legnext.ai/sdk/go/video-generation) - [Quick Start](https://docs.legnext.ai/sdk/go/quickstart) --- # Installation _Install the Legnext Java SDK_ ## Requirements - **Java**: Version 1.8 or higher - **Build Tool**: Maven 3.8.3+ or Gradle 7.2+ ## Maven Installation Add this dependency to your project's `pom.xml`: ```xml com.legnext legnext-sdk 1.0.0 ``` ## Gradle Installation Add this dependency to your `build.gradle`: ```groovy dependencies { implementation 'com.legnext:legnext-sdk:1.0.0' } ``` ## Build from Source ```bash git clone https://github.com/legnext-ai/legnext-java-sdk.git cd legnext-java-sdk mvn clean install ``` ## Verify Installation ```bash mvn dependency:tree | grep legnext ``` --- # Authentication _Set up authentication for the Legnext Java SDK_ ## Get Your API Key 1. Visit [Legnext Dashboard](https://dashboard.legnext.ai) 2. Log in to your account 3. Navigate to **API Keys** section 4. Create a new API key 5. Copy and save it securely ## Using Your API Key ### Method 1: Direct Initialization ```java import org.openapitools.client.ApiClient; import org.openapitools.client.Configuration; import org.openapitools.client.api.ImageApi; public class Example { public static void main(String[] args) { ApiClient apiClient = Configuration.getDefaultApiClient(); apiClient.setBasePath("https://api.legnext.ai"); ImageApi imageApi = new ImageApi(apiClient); String apiKey = "your-api-key-here"; // Use apiKey as parameter in method calls } } ``` ### Method 2: Environment Variable (Recommended) Set the environment variable: ```bash # macOS/Linux export LEGNEXT_API_KEY="your-api-key-here" # Windows CMD set LEGNEXT_API_KEY=your-api-key-here # Windows PowerShell $env:LEGNEXT_API_KEY="your-api-key-here" ``` Then in your code: ```java public class Example { public static void main(String[] args) { ApiClient apiClient = Configuration.getDefaultApiClient(); apiClient.setBasePath("https://api.legnext.ai"); String apiKey = System.getenv("LEGNEXT_API_KEY"); ImageApi imageApi = new ImageApi(apiClient); // Use apiKey as parameter in method calls } } ``` ### Method 3: Properties File Create a `config.properties` file: ```properties legnext.api.key=your-api-key-here legnext.api.baseurl=https://api.legnext.ai ``` Load it in your code: ```java import java.io.FileInputStream; import java.util.Properties; import org.openapitools.client.ApiClient; import org.openapitools.client.Configuration; import org.openapitools.client.api.ImageApi; public class Example { public static void main(String[] args) throws Exception { Properties props = new Properties(); props.load(new FileInputStream("config.properties")); ApiClient apiClient = Configuration.getDefaultApiClient(); apiClient.setBasePath(props.getProperty("legnext.api.baseurl")); String apiKey = props.getProperty("legnext.api.key"); ImageApi imageApi = new ImageApi(apiClient); // Use apiKey as parameter in method calls } } ``` ## Security Best Practices ⚠️ **Never hardcode API keys in your code** ✅ **Always use environment variables or configuration files** ✅ **Add configuration files to `.gitignore`** ✅ **Rotate keys regularly and revoke compromised ones** --- ## Next Steps - [Quick Start](https://docs.legnext.ai/sdk/java/quickstart) - [Image Generation API](https://docs.legnext.ai/sdk/java/image-generation) - [Video Generation API](https://docs.legnext.ai/sdk/java/video-generation) --- # Quick Start _Get started with the Legnext Java SDK_ ## 1. Add Dependency ### Maven ```xml ai.legnext legnext-java-sdk 1.0.0 ``` ### Gradle ```groovy implementation 'ai.legnext:legnext-java-sdk:1.0.0' ``` ## 2. Set API Key Set your API key as an environment variable: ```bash export LEGNEXT_API_KEY="your-api-key" ``` ## 3. Basic Example ```java import org.openapitools.client.ApiClient; import org.openapitools.client.ApiException; import org.openapitools.client.Configuration; import org.openapitools.client.api.ImageApi; import java.util.HashMap; import java.util.Map; public class QuickStart { public static void main(String[] args) { // Configure API client ApiClient apiClient = Configuration.getDefaultApiClient(); apiClient.setBasePath("https://api.legnext.ai"); String apiKey = System.getenv("LEGNEXT_API_KEY"); // Create API instance ImageApi api = new ImageApi(apiClient); try { // Generate image Map request = new HashMap<>(); request.put("text", "a beautiful sunset over mountains"); Object response = api.apiV1DiffusionPost(apiKey, request); System.out.println("Response: " + response); } catch (ApiException e) { System.err.println("Error: " + e.getMessage()); System.err.println("Status code: " + e.getCode()); System.err.println("Response body: " + e.getResponseBody()); } } } ``` ## 4. Check Task Status ```java import org.openapitools.client.api.VideoApi; VideoApi taskApi = new VideoApi(apiClient); String jobId = "your-job-id-here"; try { Object taskResponse = taskApi.apiV1JobJobIdGet(jobId, apiKey); System.out.println("Task status: " + taskResponse); } catch (ApiException e) { System.err.println("Error: " + e.getMessage()); } ``` ## Error Handling ```java try { Object response = api.apiV1DiffusionPost(apiKey, request); } catch (ApiException e) { // HTTP status code System.err.println("Status code: " + e.getCode()); // Error message System.err.println("Message: " + e.getMessage()); // Response body System.err.println("Response: " + e.getResponseBody()); // Response headers System.err.println("Headers: " + e.getResponseHeaders()); } ``` ## Available APIs - `ImageApi` - Text to image, variations, upscaling, editing - `VideoApi` - Video generation, upscaling, and task status - `AccountManagementApi` - Account balance and information --- # Image Generation _Image generation API reference for Java SDK_ ## apiV1DiffusionPost() Create a new text-to-image generation task. ```java import org.openapitools.client.ApiClient; import org.openapitools.client.api.ImageApi; import org.openapitools.client.ApiException; import java.util.HashMap; import java.util.Map; ApiClient apiClient = new ApiClient(); apiClient.setBasePath("https://api.legnext.ai"); ImageApi imageApi = new ImageApi(apiClient); String apiKey = "your-api-key-here"; // Create request body Map body = new HashMap<>(); body.put("text", "a serene mountain landscape at sunset"); body.put("callback", "https://your-domain.com/webhook"); // Optional try { var response = imageApi.apiV1DiffusionPost(apiKey, body); System.out.println("Job ID: " + response.getJobId()); } catch (ApiException e) { System.err.println("Error: " + e.getResponseBody()); } ``` **Parameters:** - `xApiKey` (String): Your API key - `body` (Object): Request body with: - `text` (String): Text prompt (1-8192 characters) - `callback` (String, optional): Webhook URL **Returns:** Response with `job_id` and `status` --- ## apiV1VaryPost() Create variations of a generated image. ```java Map body = new HashMap<>(); body.put("jobId", "original-job-id"); body.put("imageNo", 0); body.put("type", 1); // 0=Subtle, 1=Strong body.put("remixPrompt", "add more clouds"); // Optional body.put("callback", "https://your-domain.com/webhook"); // Optional try { var response = imageApi.apiV1VaryPost(apiKey, body); System.out.println("Variation Job ID: " + response.getJobId()); } catch (ApiException e) { System.err.println("Error: " + e.getResponseBody()); } ``` **Parameters:** - `jobId` (String): Original image task ID - `imageNo` (Integer): Image index (0-3) - `type` (Integer): Variation intensity (0=Subtle, 1=Strong) - `remixPrompt` (String, optional): Additional guidance - `callback` (String, optional): Webhook URL --- ## apiV1UpscalePost() Upscale a generated image. ```java Map body = new HashMap<>(); body.put("jobId", "original-job-id"); body.put("imageNo", 0); body.put("type", 1); // 0=Subtle, 1=Creative body.put("callback", "https://your-domain.com/webhook"); // Optional try { var response = imageApi.apiV1UpscalePost(apiKey, body); System.out.println("Upscale Job ID: " + response.getJobId()); } catch (ApiException e) { System.err.println("Error: " + e.getResponseBody()); } ``` **Parameters:** - `jobId` (String): Original image task ID - `imageNo` (Integer): Image index (0-3) - `type` (Integer): Upscaling type (0=Subtle, 1=Creative) - `callback` (String, optional): Webhook URL --- ## apiV1RerollPost() Regenerate with the same prompt. ```java Map body = new HashMap<>(); body.put("jobId", "original-job-id"); body.put("callback", "https://your-domain.com/webhook"); // Optional try { var response = imageApi.apiV1RerollPost(apiKey, body); System.out.println("Reroll Job ID: " + response.getJobId()); } catch (ApiException e) { System.err.println("Error: " + e.getResponseBody()); } ``` **Parameters:** - `jobId` (String): Original image task ID - `callback` (String, optional): Webhook URL --- ## apiV1BlendPost() Blend 2-5 images together. ```java import java.util.Arrays; import java.util.List; Map body = new HashMap<>(); List imageUrls = Arrays.asList( "https://example.com/image1.png", "https://example.com/image2.png" ); body.put("imgUrls", imageUrls); body.put("aspect_ratio", "1:1"); // "2:3", "1:1", or "3:2" body.put("callback", "https://your-domain.com/webhook"); // Optional try { var response = imageApi.apiV1BlendPost(apiKey, body); System.out.println("Blend Job ID: " + response.getJobId()); } catch (ApiException e) { System.err.println("Error: " + e.getResponseBody()); } ``` **Parameters:** - `imgUrls` (List): 2-5 image URLs - `aspect_ratio` (String): Output ratio ("2:3", "1:1", or "3:2") - `callback` (String, optional): Webhook URL --- ## apiV1DescribePost() Generate text descriptions from an image. ```java Map body = new HashMap<>(); body.put("imgUrl", "https://example.com/image.png"); body.put("callback", "https://your-domain.com/webhook"); // Optional try { var response = imageApi.apiV1DescribePost(apiKey, body); System.out.println("Description: " + response.getDescription()); } catch (ApiException e) { System.err.println("Error: " + e.getResponseBody()); } ``` **Parameters:** - `imgUrl` (String): Image URL - `callback` (String, optional): Webhook URL --- ## apiV1EditPost() Edit an image with text description. ```java Map body = new HashMap<>(); body.put("canvas", "original-job-id"); body.put("imgPos", 0); // Image index body.put("remixPrompt", "change the sky to sunset colors"); body.put("callback", "https://your-domain.com/webhook"); // Optional try { var response = imageApi.apiV1EditPost(apiKey, body); System.out.println("Edit Job ID: " + response.getJobId()); } catch (ApiException e) { System.err.println("Error: " + e.getResponseBody()); } ``` **Parameters:** - `canvas` (String): Original image task ID - `imgPos` (Integer): Image index - `remixPrompt` (String): Edit instruction - `callback` (String, optional): Webhook URL --- ## apiV1InpaintPost() Fill masked regions in an image. ```java Map body = new HashMap<>(); body.put("jobId", "original-job-id"); body.put("imageNo", 0); body.put("remixPrompt", "fill with forest landscape"); body.put("mask", "mask-url-or-coordinates"); body.put("callback", "https://your-domain.com/webhook"); // Optional try { var response = imageApi.apiV1InpaintPost(apiKey, body); System.out.println("Inpaint Job ID: " + response.getJobId()); } catch (ApiException e) { System.err.println("Error: " + e.getResponseBody()); } ``` **Parameters:** - `jobId` (String): Original image task ID - `imageNo` (Integer): Image index - `remixPrompt` (String): Fill instruction - `mask` (String): Mask URL or coordinates - `callback` (String, optional): Webhook URL --- ## apiV1OutpaintPost() Extend image boundaries. ```java Map body = new HashMap<>(); body.put("jobId", "original-job-id"); body.put("imageNo", 0); body.put("scale", 1.5); // 1.1 to 3.0 body.put("remixPrompt", "extend with more sky"); // Optional body.put("callback", "https://your-domain.com/webhook"); // Optional try { var response = imageApi.apiV1OutpaintPost(apiKey, body); System.out.println("Outpaint Job ID: " + response.getJobId()); } catch (ApiException e) { System.err.println("Error: " + e.getResponseBody()); } ``` **Parameters:** - `jobId` (String): Original image task ID - `imageNo` (Integer): Image index - `scale` (Double): Scale factor (1.1-3.0) - `remixPrompt` (String, optional): Extension guidance - `callback` (String, optional): Webhook URL --- ## apiV1PanPost() Create panoramic or panned views. ```java Map body = new HashMap<>(); body.put("jobId", "original-job-id"); body.put("imageNo", 0); body.put("direction", 3); // 0=Down, 1=Right, 2=Up, 3=Left body.put("scale", 1.5); // 1.1 to 3.0 body.put("remixPrompt", "add dramatic lighting"); // Optional body.put("callback", "https://your-domain.com/webhook"); // Optional try { var response = imageApi.apiV1PanPost(apiKey, body); System.out.println("Pan Job ID: " + response.getJobId()); } catch (ApiException e) { System.err.println("Error: " + e.getResponseBody()); } ``` **Parameters:** - `jobId` (String): Original image task ID - `imageNo` (Integer): Image index - `direction` (Integer): Pan direction (0=Down, 1=Right, 2=Up, 3=Left) - `scale` (Double): Scale factor (1.1-3.0) - `remixPrompt` (String, optional): Pan guidance - `callback` (String, optional): Webhook URL --- ## apiV1RemixPost() Remix an image with different prompt guidance. ```java Map body = new HashMap<>(); body.put("jobId", "original-job-id"); body.put("imageNo", 0); body.put("mode", 0); // 0=Strong, 1=Subtle body.put("remixPrompt", "change to a winter scene"); body.put("callback", "https://your-domain.com/webhook"); // Optional try { var response = imageApi.apiV1RemixPost(apiKey, body); System.out.println("Remix Job ID: " + response.getJobId()); } catch (ApiException e) { System.err.println("Error: " + e.getResponseBody()); } ``` **Parameters:** - `jobId` (String): Original image task ID - `imageNo` (Integer): Image index - `mode` (Integer): Remix intensity (0=Strong, 1=Subtle) - `remixPrompt` (String): Remix instruction - `callback` (String, optional): Webhook URL --- ## apiV1ShortenPost() Optimize and simplify prompts. ```java Map body = new HashMap<>(); body.put("prompt", "your very long and detailed prompt here..."); body.put("callback", "https://your-domain.com/webhook"); // Optional try { var response = imageApi.apiV1ShortenPost(apiKey, body); System.out.println("Optimized prompt: " + response.getShortenedPrompt()); } catch (ApiException e) { System.err.println("Error: " + e.getResponseBody()); } ``` **Parameters:** - `prompt` (String): Prompt to optimize - `callback` (String, optional): Webhook URL --- ## Next Steps - [Video Generation](https://docs.legnext.ai/sdk/java/video-generation) - [Task Management](https://docs.legnext.ai/sdk/java/task-management) - [Quick Start](https://docs.legnext.ai/sdk/java/quickstart) --- # Video Generation _Video generation API reference for Java SDK_ ## apiV1VideoDiffusionPost() Generate a video from text prompt. ```java import org.openapitools.client.ApiClient; import org.openapitools.client.api.VideoApi; import org.openapitools.client.ApiException; import java.util.HashMap; import java.util.Map; ApiClient apiClient = new ApiClient(); apiClient.setBasePath("https://api.legnext.ai"); VideoApi videoApi = new VideoApi(apiClient); String apiKey = "your-api-key-here"; // Text-to-video Map body = new HashMap<>(); body.put("prompt", "a flowing river through mountains"); body.put("videoType", 1); // Optional: 0=480p, 1=720p body.put("callback", "https://your-domain.com/webhook"); // Optional try { var response = videoApi.apiV1VideoDiffusionPost(apiKey, body); System.out.println("Job ID: " + response.getJobId()); } catch (ApiException e) { System.err.println("Error: " + e.getResponseBody()); } ``` **Image-to-video animation (using jobId + imageNo):** ```java // Animate an existing generated image Map body = new HashMap<>(); body.put("jobId", "original-image-job-id"); body.put("imageNo", 0); // Image index from original generation body.put("videoType", 1); body.put("callback", "https://your-domain.com/webhook"); // Optional try { var response = videoApi.apiV1VideoDiffusionPost(apiKey, body); System.out.println("Video Job ID: " + response.getJobId()); } catch (ApiException e) { System.err.println("Error: " + e.getResponseBody()); } ``` **Image-to-video animation (using image URL in prompt):** ```java // Animate an image using URL in prompt Map body = new HashMap<>(); body.put("prompt", "https://example.com/image.png a flowing river through mountains"); body.put("videoType", 1); body.put("callback", "https://your-domain.com/webhook"); // Optional try { var response = videoApi.apiV1VideoDiffusionPost(apiKey, body); System.out.println("Video Job ID: " + response.getJobId()); } catch (ApiException e) { System.err.println("Error: " + e.getResponseBody()); } ``` **Parameters:** - Text-only mode: - `prompt` (String): Video prompt (1-8192 characters) - `videoType` (Integer, optional): Quality (0=480p, 1=720p) - `callback` (String, optional): Webhook URL - jobId + imageNo mode: - `jobId` (String): Image generation task ID - `imageNo` (Integer): Image index (0-3) - `videoType` (Integer, optional): Quality (0=480p, 1=720p) - `callback` (String, optional): Webhook URL - Image URL in prompt mode: - `prompt` (String): "[image_url] prompt text" format (1-8192 characters) - `videoType` (Integer, optional): Quality (0=480p, 1=720p) - `callback` (String, optional): Webhook URL **Returns:** Response with `job_id` and `status` --- ## apiV1ExtendVideoPost() Extend an existing video. ```java Map body = new HashMap<>(); body.put("jobId", "original-video-job-id"); body.put("videoNo", 0); // 0-3 body.put("prompt", "continue with dramatic lighting"); // Optional body.put("callback", "https://your-domain.com/webhook"); // Optional try { var response = videoApi.apiV1ExtendVideoPost(apiKey, body); System.out.println("Extended video Job ID: " + response.getJobId()); } catch (ApiException e) { System.err.println("Error: " + e.getResponseBody()); } ``` **Parameters:** - `jobId` (String): Original video task ID - `videoNo` (Integer): Video index (0-3) - `prompt` (String, optional): Extension prompt (1-8192 characters) - `callback` (String, optional): Webhook URL --- ## apiV1VideoUpscalePost() Upscale video to higher resolution. ```java Map body = new HashMap<>(); body.put("jobId", "original-video-job-id"); body.put("videoNo", 0); // 0-3 body.put("callback", "https://your-domain.com/webhook"); // Optional try { var response = videoApi.apiV1VideoUpscalePost(apiKey, body); System.out.println("Upscaled video Job ID: " + response.getJobId()); } catch (ApiException e) { System.err.println("Error: " + e.getResponseBody()); } ``` **Parameters:** - `jobId` (String): Original video task ID - `videoNo` (Integer): Video index (0-3) - `callback` (String, optional): Webhook URL --- ## Complete Example ```java import org.openapitools.client.ApiClient; import org.openapitools.client.api.VideoApi; import org.openapitools.client.ApiException; import java.util.HashMap; import java.util.Map; public class VideoGenerationExample { public static void main(String[] args) { ApiClient apiClient = new ApiClient(); apiClient.setBasePath("https://api.legnext.ai"); VideoApi videoApi = new VideoApi(apiClient); String apiKey = System.getenv("LEGNEXT_API_KEY"); try { // Step 1: Generate initial video Map body = new HashMap<>(); body.put("prompt", "a sunset over ocean waves"); body.put("videoType", 1); var initialResponse = videoApi.apiV1VideoDiffusionPost(apiKey, body); String jobId = initialResponse.getJobId(); System.out.println("Initial video job: " + jobId); // Wait for completion (see task-management.mdx) // ... // Step 2: Extend the video Map extendBody = new HashMap<>(); extendBody.put("jobId", jobId); extendBody.put("videoNo", 0); extendBody.put("prompt", "zoom in on the waves"); var extendResponse = videoApi.apiV1ExtendVideoPost(apiKey, extendBody); System.out.println("Extended video job: " + extendResponse.getJobId()); } catch (ApiException e) { System.err.println("Error: " + e.getResponseBody()); e.printStackTrace(); } } } ``` --- ## Next Steps - [Image Generation](https://docs.legnext.ai/sdk/java/image-generation) - [Task Management](https://docs.legnext.ai/sdk/java/task-management) - [Quick Start](https://docs.legnext.ai/sdk/java/quickstart) --- # Task Management _Task status, polling, and error handling for Java SDK_ ## apiV1JobJobIdGet() Get current task status: ```java import org.openapitools.client.ApiClient; import org.openapitools.client.api.VideoApi; import org.openapitools.client.ApiException; ApiClient apiClient = new ApiClient(); apiClient.setBasePath("https://api.legnext.ai"); VideoApi videoApi = new VideoApi(apiClient); String apiKey = "your-api-key-here"; String jobId = "job-123"; try { var task = videoApi.apiV1JobJobIdGet(jobId, apiKey); System.out.println("Status: " + task.getStatus()); System.out.println("Progress: " + task.getProgress() + "%"); if ("completed".equals(task.getStatus())) { System.out.println("Result: " + task.getOutput()); } } catch (ApiException e) { System.err.println("Error: " + e.getResponseBody()); } ``` --- ## Polling for Completion Wait for task completion with polling: ```java public class TaskPoller { public static void waitForCompletion( VideoApi api, String jobId, String apiKey, int timeoutSeconds, int pollIntervalSeconds ) throws ApiException, InterruptedException { long startTime = System.currentTimeMillis(); long timeout = timeoutSeconds * 1000; while (true) { var task = api.apiV1JobJobIdGet(jobId, apiKey); String status = task.getStatus(); System.out.println("Current status: " + status); if ("completed".equals(status)) { System.out.println("Task completed successfully!"); System.out.println("Output: " + task.getOutput()); return; } else if ("failed".equals(status)) { throw new RuntimeException("Task failed: " + task.getError()); } // Check timeout if (System.currentTimeMillis() - startTime > timeout) { throw new RuntimeException("Task timeout after " + timeoutSeconds + " seconds"); } // Wait before next poll Thread.sleep(pollIntervalSeconds * 1000); } } } ``` **Usage:** ```java try { TaskPoller.waitForCompletion(imageApi, jobId, apiKey, 300, 3); } catch (Exception e) { System.err.println("Error: " + e.getMessage()); } ``` --- ## Complete Example with Error Handling ```java import org.openapitools.client.ApiClient; import org.openapitools.client.api.VideoApi; import org.openapitools.client.ApiException; import java.util.HashMap; import java.util.Map; public class ImageGenerationWithPolling { public static void main(String[] args) { ApiClient apiClient = new ApiClient(); apiClient.setBasePath("https://api.legnext.ai"); VideoApi videoApi = new VideoApi(apiClient); String apiKey = System.getenv("LEGNEXT_API_KEY"); try { // Step 1: Start generation Map body = new HashMap<>(); body.put("text", "a beautiful sunset over mountains"); var response = imageApi.apiV1DiffusionPost(apiKey, body); String jobId = response.getJobId(); System.out.println("Job started: " + jobId); // Step 2: Poll for completion TaskPoller.waitForCompletion(imageApi, jobId, apiKey, 600, 3); // Step 3: Get final result var result = videoApi.apiV1JobJobIdGet(jobId, apiKey); System.out.println("Image URLs: " + result.getOutput().getImageUrls()); } catch (ApiException e) { handleApiException(e); } catch (InterruptedException e) { System.err.println("Polling interrupted: " + e.getMessage()); } catch (Exception e) { System.err.println("Unexpected error: " + e.getMessage()); e.printStackTrace(); } } private static void handleApiException(ApiException e) { int statusCode = e.getCode(); String responseBody = e.getResponseBody(); switch (statusCode) { case 400: System.err.println("Validation error: " + responseBody); break; case 401: System.err.println("Authentication error: Invalid API key"); break; case 404: System.err.println("Resource not found: " + responseBody); break; case 429: System.err.println("Rate limit exceeded. Please retry later."); break; case 500: case 502: case 503: System.err.println("Server error: " + responseBody); break; default: System.err.println("API error (" + statusCode + "): " + responseBody); } } } ``` --- ## Error Handling **Common HTTP Status Codes:** | Status Code | Description | Action | |-------------|-------------|--------| | 400 | Invalid request parameters | Check request body format | | 401 | Invalid API key | Verify API key is correct | | 404 | Resource not found | Check job ID exists | | 429 | Rate limit exceeded | Wait and retry with backoff | | 500/502/503 | Server error | Retry with exponential backoff | **Handling Different Error Scenarios:** ```java try { var response = imageApi.apiV1DiffusionPost(apiKey, body); } catch (ApiException e) { if (e.getCode() == 429) { // Rate limited - implement backoff Thread.sleep(5000); // Retry request } else if (e.getCode() >= 500) { // Server error - retry with exponential backoff for (int i = 0; i < 3; i++) { Thread.sleep((long) Math.pow(2, i) * 1000); try { var response = imageApi.apiV1DiffusionPost(apiKey, body); break; // Success } catch (ApiException retryEx) { if (i == 2) throw retryEx; // Last retry failed } } } else { // Other errors - log and handle System.err.println("API Error: " + e.getResponseBody()); throw e; } } ``` --- ## Async Operations with CompletableFuture For non-blocking operations: ```java import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class AsyncExample { private static final ExecutorService executor = Executors.newFixedThreadPool(5); public static CompletableFuture generateImageAsync( VideoApi api, String apiKey, String prompt ) { return CompletableFuture.supplyAsync(() -> { try { Map body = new HashMap<>(); body.put("text", prompt); var response = api.apiV1DiffusionPost(apiKey, body); String jobId = response.getJobId(); // Poll for completion TaskPoller.waitForCompletion(api, jobId, apiKey, 600, 3); var result = api.apiV1JobJobIdGet(jobId, apiKey); return result.getOutput().getImageUrls().get(0); } catch (Exception e) { throw new RuntimeException(e); } }, executor); } public static void main(String[] args) { ApiClient apiClient = new ApiClient(); apiClient.setBasePath("https://api.legnext.ai"); VideoApi videoApi = new VideoApi(apiClient); String apiKey = System.getenv("LEGNEXT_API_KEY"); // Generate multiple images concurrently CompletableFuture future1 = generateImageAsync(api, apiKey, "sunset"); CompletableFuture future2 = generateImageAsync(api, apiKey, "mountains"); CompletableFuture future3 = generateImageAsync(api, apiKey, "ocean"); CompletableFuture.allOf(future1, future2, future3).join(); try { System.out.println("Image 1: " + future1.get()); System.out.println("Image 2: " + future2.get()); System.out.println("Image 3: " + future3.get()); } catch (Exception e) { e.printStackTrace(); } finally { executor.shutdown(); } } } ``` --- ## Learn More - [Image Generation API](https://docs.legnext.ai/sdk/java/image-generation) - [Video Generation API](https://docs.legnext.ai/sdk/java/video-generation) - [Quick Start](https://docs.legnext.ai/sdk/java/quickstart) --- # Installation _Install the Legnext PHP SDK_ ## Requirements - **PHP**: Version 7.4 or higher - **Composer**: Latest version ## Install via Composer ```bash composer require legnext-api/php-sdk ``` ## Manual Installation Download the SDK and include it in your project: ```php ``` ## Verify Installation ```bash composer show legnext-api/php-sdk ``` --- # Authentication _Set up API authentication for PHP SDK_ ## Getting Your API Key 1. Visit [Legnext.ai Dashboard](https://legnext.ai/dashboard) 2. Navigate to API Keys section 3. Generate a new API key 4. Copy and store securely ## Authentication Methods ### Method 1: Environment Variables (Recommended) Set your API key as an environment variable: ```bash export LEGNEXT_API_KEY="your-api-key-here" ``` Then use it in your PHP code: ```php setApiKey('x-api-key', getenv('LEGNEXT_API_KEY')); $config->setHost('https://api.legnext.ai'); // Create API instance $api = new OpenAPI\Client\Api\ImageApi( new GuzzleHttp\Client(), $config ); // Now you can use the API // ... ?> ``` ### Method 2: Direct Initialization Hardcode the API key directly (not recommended for production): ```php setApiKey('x-api-key', 'your-api-key-here'); $config->setHost('https://api.legnext.ai'); $api = new OpenAPI\Client\Api\ImageApi( new GuzzleHttp\Client(), $config ); ?> ``` ### Method 3: Using vlucas/phpdotenv Use the `vlucas/phpdotenv` package to load from `.env` files: ```bash composer require vlucas/phpdotenv ``` ```php load(); // Configure API client $config = OpenAPI\Client\Configuration::getDefaultConfiguration(); $config->setApiKey('x-api-key', $_ENV['LEGNEXT_API_KEY']); $config->setHost('https://api.legnext.ai'); $api = new OpenAPI\Client\Api\ImageApi( new GuzzleHttp\Client(), $config ); ?> ``` **.env file:** ``` LEGNEXT_API_KEY=your-api-key-here ``` ### Method 4: Configuration File Load API key from a configuration file: ```php setApiKey('x-api-key', $config_data['api_key']); $config->setHost('https://api.legnext.ai'); $api = new OpenAPI\Client\Api\ImageApi( new GuzzleHttp\Client(), $config ); ?> ``` **config.php:** ```php 'your-api-key-here', 'environment' => 'development', ]; ?> ``` ### Method 5: Framework Integration (Laravel) For Laravel applications, use environment variables: **.env:** ``` LEGNEXT_API_KEY=your-api-key-here ``` **config/legnext.php:** ```php env('LEGNEXT_API_KEY'), 'host' => env('LEGNEXT_HOST', 'https://api.legnext.ai'), ]; ?> ``` **Usage in Laravel:** ```php setApiKey('x-api-key', config('legnext.api_key')); $config->setHost(config('legnext.host')); $this->api = new ImageApi( new \GuzzleHttp\Client(), $config ); } public function generateImage($text) { // Implementation } } ?> ``` --- ## Complete Configuration Example ```php setApiKey('x-api-key', getenv('LEGNEXT_API_KEY')); // Required: API Host $config->setHost('https://api.legnext.ai'); // Optional: Set debugging mode $config->setDebug(getenv('LEGNEXT_DEBUG') === 'true'); // Optional: Set timeout (in seconds) $config->setCurlTimeout(120); // Optional: Set custom user agent $config->setUserAgent('MyApp/1.0'); // Optional: SSL verification (recommended: true) $config->setSSLVerification(true); $api = new OpenAPI\Client\Api\ImageApi( new GuzzleHttp\Client(), $config ); ?> ``` --- ## Security Best Practices 1. **Never commit API keys to version control** ``` # .gitignore .env config.php ``` 2. **Use environment variables in production** ```bash # Set in your deployment environment export LEGNEXT_API_KEY="your-production-key" ``` 3. **Rotate keys regularly** - Generate new keys periodically - Revoke old keys after rotation 4. **Use different keys for development and production** ```php setApiKey('x-api-key', $apiKey); ?> ``` 5. **Restrict API key permissions** - Use the minimum required permissions - Monitor usage through the dashboard 6. **Enable SSL verification** ```php setSSLVerification(true); ?> ``` 7. **Protect configuration files** ```php getenv('LEGNEXT_API_KEY'), ]; ?> ``` --- ## Testing Authentication Verify your API key is working: ```php setApiKey('x-api-key', $apiKey); $config->setHost('https://api.legnext.ai'); $accountApi = new OpenAPI\Client\Api\AccountManagementApi( new GuzzleHttp\Client(), $config ); try { // Test with account balance endpoint $response = $accountApi->apiAccountBalanceGet($apiKey); echo "✅ Authentication successful!\n"; echo "Balance: " . $response->getBalance() . " credits\n"; } catch (OpenAPI\Client\ApiException $e) { if ($e->getCode() === 401) { echo "❌ Authentication failed: Invalid API key\n"; } else { echo "❌ Error: " . $e->getMessage() . "\n"; } } ?> ``` --- ## Debugging Enable debugging to see HTTP requests and responses: ```php setApiKey('x-api-key', getenv('LEGNEXT_API_KEY')); $config->setHost('https://api.legnext.ai'); // Enable debug mode $config->setDebug(true); // Set debug file (optional) $config->setDebugFile('/path/to/debug.log'); $api = new OpenAPI\Client\Api\ImageApi( new GuzzleHttp\Client(), $config ); ?> ``` --- ## Error Handling ```php generateImage($request); } catch (OpenAPI\Client\ApiException $e) { $statusCode = $e->getCode(); $errorBody = $e->getResponseBody(); switch ($statusCode) { case 401: echo "Authentication error: Invalid API key\n"; break; case 400: echo "Validation error: " . $errorBody . "\n"; break; case 404: echo "Resource not found\n"; break; case 429: echo "Rate limit exceeded. Please retry later.\n"; break; case 500: case 502: case 503: echo "Server error: " . $errorBody . "\n"; break; default: echo "API error ({$statusCode}): " . $errorBody . "\n"; } } ?> ``` --- ## Next Steps - [Image Generation](https://docs.legnext.ai/sdk/php/image-generation) - [Video Generation](https://docs.legnext.ai/sdk/php/video-generation) - [Task Management](https://docs.legnext.ai/sdk/php/task-management) - [Quick Start](https://docs.legnext.ai/sdk/php/quickstart) --- # Quick Start _Get started with the Legnext PHP SDK_ ## 1. Install ```bash composer require legnext-api/php-sdk ``` ## 2. Set API Key ```php ``` ## 3. Basic Example ```php setHost('https://api.legnext.ai'); $config->setApiKey('x-api-key', $apiKey); // Create API instance $api = new OpenAPI\Client\Api\ImageApi( new GuzzleHttp\Client(), $config ); try { // Generate image $body = [ 'text' => 'a beautiful sunset over mountains' ]; $response = $api->apiV1DiffusionPost($apiKey, $body); echo "Job ID: " . $response->getJobId() . "\n"; echo "Status: " . $response->getStatus() . "\n"; } catch (Exception $e) { echo "Error: " . $e->getMessage() . "\n"; } ?> ``` ## 4. Check Task Status ```php apiV1JobJobIdGet($jobId, $apiKey); echo "Status: " . $taskResponse->getStatus() . "\n"; echo "Task Type: " . $taskResponse->getTaskType() . "\n"; if ($taskResponse->getOutput() !== null) { $output = $taskResponse->getOutput(); if ($output->getImageUrls() !== null) { echo "Images:\n"; foreach ($output->getImageUrls() as $url) { echo " - " . $url . "\n"; } } } } catch (Exception $e) { echo "Error: " . $e->getMessage() . "\n"; } ?> ``` ## Error Handling ```php apiV1DiffusionPost($apiKey, $body); } catch (OpenAPI\Client\ApiException $e) { echo "HTTP Status Code: " . $e->getCode() . "\n"; echo "Error Message: " . $e->getMessage() . "\n"; echo "Response Body: " . $e->getResponseBody() . "\n"; } ?> ``` ## Available APIs - `OpenAPI\Client\Api\ImageApi` - Text to image, variations, upscaling, editing - `OpenAPI\Client\Api\VideoApi` - Video generation, upscaling, and task status - `OpenAPI\Client\Api\AccountManagementApi` - Account balance and information --- # Image Generation _Image generation API reference for PHP SDK_ ## generateImage() Create a new text-to-image generation task. ```php setApiKey('x-api-key', getenv('LEGNEXT_API_KEY')); $config->setHost('https://api.legnext.ai'); $api = new ImageGenerationApi(null, $config); try { $request = new DiffusionRequest(); $request->setText('a serene mountain landscape at sunset'); $request->setCallback('https://your-domain.com/webhook'); $response = $api->generateImage($request); echo "Job ID: " . $response->getJobId() . "\n"; echo "Status: " . $response->getStatus() . "\n"; } catch (\OpenAPI\Client\ApiException $e) { echo "Error: " . $e->getMessage() . "\n"; } ?> ``` **Parameters:** - `text` (string): Text prompt (1-8192 characters) - `callback` (string, optional): Webhook URL for completion notification **Returns:** Response with `job_id` and `status` --- ## varyImage() Create variations of a generated image. ```php setJobId('original-job-id'); $request->setImageNo(0); $request->setType(1); // 0=Subtle, 1=Strong $request->setRemixPrompt('add more clouds'); $request->setCallback('https://your-domain.com/webhook'); $response = $api->varyImage($request); echo "Variation Job ID: " . $response->getJobId() . "\n"; ?> ``` **Parameters:** - `job_id` (string): Original image job ID - `image_no` (int): Image index (0-3) - `type` (int): Variation type (0=Subtle, 1=Strong) - `remix_prompt` (string, optional): Additional prompt for variation - `callback` (string, optional): Webhook URL for completion notification --- ## upscaleImage() Upscale a generated image to higher resolution. ```php setJobId('original-job-id'); $request->setImageNo(0); $request->setType(1); // 0=Subtle, 1=Creative $request->setCallback('https://your-domain.com/webhook'); $response = $api->upscaleImage($request); echo "Upscale Job ID: " . $response->getJobId() . "\n"; ?> ``` **Parameters:** - `job_id` (string): Original image job ID - `image_no` (int): Image index (0-3) - `type` (int): Upscale type (0=Subtle, 1=Creative) - `callback` (string, optional): Webhook URL for completion notification --- ## rerollImage() Regenerate with the same prompt. ```php setJobId('original-job-id'); $request->setCallback('https://your-domain.com/webhook'); $response = $api->rerollImage($request); echo "Reroll Job ID: " . $response->getJobId() . "\n"; ?> ``` **Parameters:** - `job_id` (string): Original image job ID - `callback` (string, optional): Webhook URL for completion notification --- ## blendImages() Blend 2-5 images together. ```php setImgUrls([ 'https://example.com/image1.png', 'https://example.com/image2.png' ]); $request->setAspectRatio('1:1'); // Options: 1:1, 16:9, 9:16, 3:2, 2:3 $request->setCallback('https://your-domain.com/webhook'); $response = $api->blendImages($request); echo "Blend Job ID: " . $response->getJobId() . "\n"; ?> ``` **Parameters:** - `img_urls` (array): Array of 2-5 image URLs - `aspect_ratio` (string, optional): Output aspect ratio (1:1, 16:9, 9:16, 3:2, 2:3) - `callback` (string, optional): Webhook URL for completion notification --- ## describeImage() Generate text descriptions from an image. ```php setImgUrl('https://example.com/image.png'); $request->setCallback('https://your-domain.com/webhook'); $response = $api->describeImage($request); echo "Describe Job ID: " . $response->getJobId() . "\n"; ?> ``` **Parameters:** - `img_url` (string): URL of the image to describe - `callback` (string, optional): Webhook URL for completion notification --- ## editImage() Edit an image with text description. ```php setJobId('original-job-id'); $request->setImageNo(0); $request->setCanvas('full'); // Canvas area: full, object, background $request->setImgPos('center'); // Image position: center, top, bottom, left, right $request->setRemixPrompt('change the sky to sunset colors'); $request->setCallback('https://your-domain.com/webhook'); $response = $api->editImage($request); echo "Edit Job ID: " . $response->getJobId() . "\n"; ?> ``` **Parameters:** - `job_id` (string): Original image job ID - `image_no` (int): Image index (0-3) - `canvas` (string): Canvas area (full, object, background) - `img_pos` (string): Image position (center, top, bottom, left, right) - `remix_prompt` (string): Edit instructions - `callback` (string, optional): Webhook URL for completion notification --- ## inpaintImage() Fill masked regions in an image. ```php setJobId('original-job-id'); $request->setImageNo(0); $request->setRemixPrompt('fill with forest landscape'); $request->setMask([ 'type' => 'url', // 'url' or 'coordinates' 'value' => 'mask-url' ]); $request->setCallback('https://your-domain.com/webhook'); $response = $api->inpaintImage($request); echo "Inpaint Job ID: " . $response->getJobId() . "\n"; ?> ``` **Parameters:** - `job_id` (string): Original image job ID - `image_no` (int): Image index (0-3) - `remix_prompt` (string): Inpainting prompt - `mask` (array): Mask object with type ('url' or 'coordinates') and value - `callback` (string, optional): Webhook URL for completion notification --- ## outpaintImage() Extend image boundaries. ```php setJobId('original-job-id'); $request->setImageNo(0); $request->setScale(1.5); // Scale factor (1.1-3.0) $request->setRemixPrompt('extend with natural landscape'); $request->setCallback('https://your-domain.com/webhook'); $response = $api->outpaintImage($request); echo "Outpaint Job ID: " . $response->getJobId() . "\n"; ?> ``` **Parameters:** - `job_id` (string): Original image job ID - `image_no` (int): Image index (0-3) - `scale` (float): Expansion scale factor (1.1-3.0) - `remix_prompt` (string, optional): Outpaint prompt - `callback` (string, optional): Webhook URL for completion notification --- ## panImage() Create panoramic or panned views. ```php setJobId('original-job-id'); $request->setImageNo(0); $request->setDirection(1); // 0=Down, 1=Right, 2=Up, 3=Left $request->setScale(1.5); // Scale factor (1.1-3.0) $request->setRemixPrompt('continue the landscape'); $request->setCallback('https://your-domain.com/webhook'); $response = $api->panImage($request); echo "Pan Job ID: " . $response->getJobId() . "\n"; ?> ``` **Parameters:** - `job_id` (string): Original image job ID - `image_no` (int): Image index (0-3) - `direction` (int): Pan direction (0=Down, 1=Right, 2=Up, 3=Left) - `scale` (float): Scale factor (1.1-3.0) - `remix_prompt` (string, optional): Pan prompt - `callback` (string, optional): Webhook URL for completion notification --- ## remixImage() Create variations using remix modes (strong or subtle modification). ```php setJobId('original-job-id'); $request->setImageNo(0); $request->setMode(0); // 0=Strong, 1=Subtle $request->setRemixPrompt('change the lighting to blue hour'); $request->setCallback('https://your-domain.com/webhook'); $response = $api->remixImage($request); echo "Remix Job ID: " . $response->getJobId() . "\n"; ?> ``` **Parameters:** - `job_id` (string): Original image job ID - `image_no` (int): Image index (0-3) - `mode` (int): Remix mode (0=Strong, 1=Subtle) - `remix_prompt` (string, optional): Remix instructions - `callback` (string, optional): Webhook URL for completion notification --- ## shortenPrompt() Optimize and simplify prompts. ```php setPrompt('your very long and detailed prompt here with lots of unnecessary words and descriptions that could be made more concise...'); $request->setCallback('https://your-domain.com/webhook'); $response = $api->shortenPrompt($request); echo "Shortened prompt: " . $response->getShortenedPrompt() . "\n"; ?> ``` **Parameters:** - `prompt` (string): Long prompt to optimize - `callback` (string, optional): Webhook URL for completion notification **Returns:** Response with `shortened_prompt` --- ## Complete Example ```php setApiKey('x-api-key', getenv('LEGNEXT_API_KEY')); $config->setHost('https://api.legnext.ai'); $api = new ImageGenerationApi(null, $config); try { // Step 1: Generate image $request = new DiffusionRequest(); $request->setText('a beautiful sunset over mountains'); $response = $api->generateImage($request); $jobId = $response->getJobId(); echo "Image generation started: {$jobId}\n"; // Step 2: Wait for completion (see Task Management docs) // ... // Step 3: Upscale the first image $upscaleRequest = new UpscaleRequest(); $upscaleRequest->setJobId($jobId); $upscaleRequest->setImageNo(0); $upscaleRequest->setType(1); $upscaleResponse = $api->upscaleImage($upscaleRequest); echo "Upscale started: " . $upscaleResponse->getJobId() . "\n"; } catch (\OpenAPI\Client\ApiException $e) { echo "HTTP Status: " . $e->getCode() . "\n"; echo "Error Message: " . $e->getMessage() . "\n"; echo "Response Body: " . $e->getResponseBody() . "\n"; } ?> ``` --- ## Error Handling ```php generateImage($request); } catch (\OpenAPI\Client\ApiException $e) { $statusCode = $e->getCode(); $errorBody = $e->getResponseBody(); switch ($statusCode) { case 400: echo "Validation error: Check request parameters\n"; break; case 401: echo "Authentication error: Invalid API key\n"; break; case 404: echo "Resource not found\n"; break; case 429: echo "Rate limit exceeded. Please retry later.\n"; break; case 500: case 502: case 503: echo "Server error. Please retry.\n"; break; default: echo "API error ({$statusCode}): {$errorBody}\n"; } } ?> ``` --- ## Retry Logic ```php generateImage($request); } catch (\OpenAPI\Client\ApiException $e) { if ($e->getCode() === 429) { // Rate limited - wait and retry $retries++; sleep(5); continue; } elseif ($e->getCode() >= 500) { // Server error - exponential backoff $retries++; $delay = pow(2, $retries); sleep($delay); if ($retries >= $maxRetries) { throw $e; } continue; } else { // Other errors - don't retry throw $e; } } } throw new Exception("Max retries exceeded"); } // Usage $request = new DiffusionRequest(); $request->setText('a beautiful landscape'); try { $response = generateWithRetry($api, $request, 3); echo "Job ID: " . $response->getJobId() . "\n"; } catch (Exception $e) { echo "Failed after retries: " . $e->getMessage() . "\n"; } ?> ``` --- ## Next Steps - [Video Generation](https://docs.legnext.ai/sdk/php/video-generation) - [Task Management](https://docs.legnext.ai/sdk/php/task-management) - [Quick Start](https://docs.legnext.ai/sdk/php/quickstart) --- # Video Generation _Video generation API reference for PHP SDK_ ## generateVideo() Generate a video from text prompt with optional image URL. ```php setApiKey('x-api-key', getenv('LEGNEXT_API_KEY')); $config->setHost('https://api.legnext.ai'); $api = new VideoGenerationApi(null, $config); try { // Generate from text only $request = new VideoDiffusionRequest(); $request->setPrompt('a flowing river through mountains'); $request->setVideoType(1); // 0=480p, 1=720p $request->setCallback('https://your-domain.com/webhook'); $response = $api->generateVideo($request); echo "Job ID: " . $response->getJobId() . "\n"; echo "Status: " . $response->getStatus() . "\n"; } catch (\OpenAPI\Client\ApiException $e) { echo "Error: " . $e->getMessage() . "\n"; } ?> ``` **Generate from Image URL in Prompt:** ```php setPrompt('https://example.com/image.png a flowing river through mountains'); $request->setVideoType(1); $request->setCallback('https://your-domain.com/webhook'); $response = $api->generateVideo($request); echo "Job ID: " . $response->getJobId() . "\n"; ?> ``` **Generate from Image Animation (using job_id and image_no):** ```php setJobId('previous-generation-job-id'); // Reference to previous image generation $request->setImageNo(0); // Image index to animate $request->setPrompt('continue the flowing motion smoothly'); $request->setVideoType(1); $request->setCallback('https://your-domain.com/webhook'); $response = $api->generateVideo($request); echo "Job ID: " . $response->getJobId() . "\n"; ?> ``` **Parameters:** *Text-only generation:* - `prompt` (string): Video prompt (1-8192 characters) - `video_type` (int, optional): Quality (0=480p, 1=720p) - `callback` (string, optional): Webhook URL *Image URL in prompt:* - `prompt` (string): "[image_url] prompt text" format (1-8192 characters) - `video_type` (int, optional): Quality (0=480p, 1=720p) - `callback` (string, optional): Webhook URL *Image animation:* - `job_id` (string): Previous image generation job ID - `image_no` (int): Image index to animate (0-3) - `prompt` (string, optional): Animation prompt (1-8192 characters) - `video_type` (int, optional): Quality (0=480p, 1=720p) - `callback` (string, optional): Webhook URL **Returns:** Response with `job_id` and `status` --- ## extendVideo() Extend an existing video. ```php setJobId('original-video-job-id'); $request->setVideoNo(0); $request->setPrompt('continue with dramatic lighting'); $request->setCallback('https://your-domain.com/webhook'); $response = $api->extendVideo($request); echo "Extension Job ID: " . $response->getJobId() . "\n"; ?> ``` **Parameters:** - `job_id` (string): Original video task ID - `video_no` (int): Video index (0-3) - `prompt` (string, optional): Extension prompt (1-8192 characters) - `callback` (string, optional): Webhook URL **Returns:** Response with `job_id` and `status` --- ## upscaleVideo() Upscale video to higher resolution. ```php setJobId('original-video-job-id'); $request->setVideoNo(0); $request->setCallback('https://your-domain.com/webhook'); $response = $api->upscaleVideo($request); echo "Upscale Job ID: " . $response->getJobId() . "\n"; ?> ``` **Parameters:** - `job_id` (string): Original video task ID - `video_no` (int): Video index (0-3) - `callback` (string, optional): Webhook URL **Returns:** Response with `job_id` and `status` --- ## Complete Example ```php setApiKey('x-api-key', getenv('LEGNEXT_API_KEY')); $config->setHost('https://api.legnext.ai'); $api = new VideoGenerationApi(null, $config); try { // Step 1: Generate video $request = new VideoDiffusionRequest(); $request->setPrompt('a beautiful sunset over the ocean'); $request->setVideoType(1); $response = $api->generateVideo($request); $jobId = $response->getJobId(); echo "Video generation started: {$jobId}\n"; // Step 2: Wait for completion (see Task Management docs) // ... // Step 3: Extend the video $extendRequest = new ExtendVideoRequest(); $extendRequest->setJobId($jobId); $extendRequest->setVideoNo(0); $extendRequest->setPrompt('continue with dramatic clouds'); $extendResponse = $api->extendVideo($extendRequest); echo "Video extension started: " . $extendResponse->getJobId() . "\n"; // Step 4: Upscale the extended video $upscaleRequest = new VideoUpscaleRequest(); $upscaleRequest->setJobId($extendResponse->getJobId()); $upscaleRequest->setVideoNo(0); $upscaleResponse = $api->upscaleVideo($upscaleRequest); echo "Video upscale started: " . $upscaleResponse->getJobId() . "\n"; } catch (\OpenAPI\Client\ApiException $e) { echo "HTTP Status: " . $e->getCode() . "\n"; echo "Error Message: " . $e->getMessage() . "\n"; echo "Response Body: " . $e->getResponseBody() . "\n"; } ?> ``` --- ## Error Handling ```php generateVideo($request); } catch (\OpenAPI\Client\ApiException $e) { $statusCode = $e->getCode(); $errorBody = $e->getResponseBody(); switch ($statusCode) { case 400: echo "Validation error: Check request parameters\n"; break; case 401: echo "Authentication error: Invalid API key\n"; break; case 404: echo "Resource not found\n"; break; case 429: echo "Rate limit exceeded. Please retry later.\n"; break; case 500: case 502: case 503: echo "Server error. Please retry.\n"; break; default: echo "API error ({$statusCode}): {$errorBody}\n"; } } ?> ``` --- ## Retry Logic ```php generateVideo($request); } catch (\OpenAPI\Client\ApiException $e) { if ($e->getCode() === 429) { // Rate limited - wait and retry $retries++; sleep(5); continue; } elseif ($e->getCode() >= 500) { // Server error - exponential backoff $retries++; $delay = pow(2, $retries); sleep($delay); if ($retries >= $maxRetries) { throw $e; } continue; } else { // Other errors - don't retry throw $e; } } } throw new Exception("Max retries exceeded"); } // Usage $request = new VideoDiffusionRequest(); $request->setPrompt('a flowing river'); $request->setVideoType(1); try { $response = generateVideoWithRetry($api, $request, 3); echo "Job ID: " . $response->getJobId() . "\n"; } catch (Exception $e) { echo "Failed after retries: " . $e->getMessage() . "\n"; } ?> ``` --- ## Asynchronous Processing with Promises For modern PHP with async support (using ReactPHP or Amp): ```php generateVideo($request); $resolve($response); } catch (\OpenAPI\Client\ApiException $e) { $reject($e); } }); } // Usage $promise = generateVideoAsync($api, $request); $promise->then( function ($response) { echo "Job ID: " . $response->getJobId() . "\n"; }, function (\OpenAPI\Client\ApiException $e) { echo "Error: " . $e->getMessage() . "\n"; } ); $loop->run(); ?> ``` --- ## Processing Multiple Videos ```php setPrompt($prompt); $request->setVideoType(1); $response = $api->generateVideo($request); $results[] = [ 'prompt' => $prompt, 'job_id' => $response->getJobId(), 'status' => 'started' ]; } catch (\OpenAPI\Client\ApiException $e) { $results[] = [ 'prompt' => $prompt, 'error' => $e->getMessage(), 'status' => 'failed' ]; } } return $results; } // Usage $prompts = ['sunset', 'mountains', 'ocean']; $results = processMultipleVideos($api, $prompts); foreach ($results as $result) { if (isset($result['error'])) { echo "Error for '{$result['prompt']}': {$result['error']}\n"; } else { echo "Video '{$result['prompt']}': {$result['job_id']}\n"; } } ?> ``` --- ## Next Steps - [Image Generation](https://docs.legnext.ai/sdk/php/image-generation) - [Task Management](https://docs.legnext.ai/sdk/php/task-management) - [Quick Start](https://docs.legnext.ai/sdk/php/quickstart) --- # Task Management _Task status, polling, and error handling for PHP SDK_ ## getTaskStatus() Get current task status: ```php setApiKey('x-api-key', getenv('LEGNEXT_API_KEY')); $config->setHost('https://api.legnext.ai'); $taskApi = new TaskManagementApi(null, $config); try { $jobId = 'job-123'; $task = $taskApi->getTaskStatus($jobId); echo "Status: " . $task->getStatus() . "\n"; echo "Progress: " . $task->getProgress() . "%\n"; if ($task->getStatus() === 'completed') { echo "Result: " . print_r($task->getOutput(), true) . "\n"; } } catch (\OpenAPI\Client\ApiException $e) { echo "Error: " . $e->getMessage() . "\n"; } ?> ``` --- ## Polling for Completion Wait for task completion with polling: ```php getTaskStatus($jobId); echo "Current status: " . $task->getStatus() . "\n"; if ($task->getStatus() === 'completed') { echo "Task completed successfully!\n"; echo "Output: " . print_r($task->getOutput(), true) . "\n"; return $task; } elseif ($task->getStatus() === 'failed') { throw new Exception("Task failed: " . $task->getError()); } // Check timeout $elapsed = time() - $startTime; if ($elapsed > $timeout) { throw new Exception("Task timeout after {$timeoutSeconds} seconds"); } // Wait before next poll sleep($pollIntervalSeconds); } } ?> ``` **Usage:** ```php getMessage() . "\n"; } ?> ``` --- ## Complete Example with Error Handling ```php setApiKey('x-api-key', getenv('LEGNEXT_API_KEY')); $config->setHost('https://api.legnext.ai'); function waitForCompletion($taskApi, $jobId, $timeoutSeconds = 300, $pollIntervalSeconds = 3) { $startTime = time(); while (true) { $task = $taskApi->getTaskStatus($jobId); if ($task->getStatus() === 'completed') { return $task; } elseif ($task->getStatus() === 'failed') { throw new Exception("Task failed: " . $task->getError()); } $elapsed = time() - $startTime; if ($elapsed > $timeoutSeconds) { throw new Exception("Task timeout after {$timeoutSeconds} seconds"); } sleep($pollIntervalSeconds); } } function handleApiError($e) { $statusCode = $e->getCode(); $errorBody = $e->getResponseBody(); switch ($statusCode) { case 400: echo "Validation error: {$errorBody}\n"; break; case 401: echo "Authentication error: Invalid API key\n"; break; case 404: echo "Resource not found: {$errorBody}\n"; break; case 429: echo "Rate limit exceeded. Please retry later.\n"; break; case 500: case 502: case 503: echo "Server error: {$errorBody}\n"; break; default: echo "API error ({$statusCode}): {$errorBody}\n"; } } function generateImageWithPolling() { global $config; $imageApi = new ImageGenerationApi(null, $config); $taskApi = new TaskManagementApi(null, $config); try { // Step 1: Start generation $request = new DiffusionRequest(); $request->setText('a beautiful sunset over mountains'); $response = $imageApi->generateImage($request); $jobId = $response->getJobId(); echo "Job started: {$jobId}\n"; // Step 2: Poll for completion $result = waitForCompletion($taskApi, $jobId, 600, 3); // Step 3: Get final result $output = $result->getOutput(); if ($output !== null && $output->getImageUrls() !== null) { echo "Image URLs: " . print_r($output->getImageUrls(), true) . "\n"; } } catch (\OpenAPI\Client\ApiException $e) { handleApiError($e); } catch (Exception $e) { echo "Error: " . $e->getMessage() . "\n"; } } generateImageWithPolling(); ?> ``` --- ## Error Handling **HTTP Error Handling:** ```php getTaskStatus($jobId); } catch (\OpenAPI\Client\ApiException $e) { $statusCode = $e->getCode(); $errorBody = $e->getResponseBody(); switch ($statusCode) { case 400: echo "Validation error: Check request parameters\n"; break; case 401: echo "Authentication error: Invalid API key\n"; break; case 404: echo "Resource not found: Check job ID exists\n"; break; case 429: echo "Rate limit exceeded. Please retry later.\n"; break; case 500: case 502: case 503: echo "Server error. Please retry with backoff.\n"; break; default: echo "API error ({$statusCode}): {$errorBody}\n"; } } ?> ``` **Common HTTP Status Codes:** | Status Code | Description | Action | |-------------|-------------|--------| | 400 | Invalid request parameters | Check request body format | | 401 | Invalid API key | Verify API key is correct | | 404 | Resource not found | Check job ID exists | | 429 | Rate limit exceeded | Wait and retry with backoff | | 500/502/503 | Server error | Retry with exponential backoff | **Retry Logic with Exponential Backoff:** ```php generateImage($request); } catch (\OpenAPI\Client\ApiException $e) { if ($e->getCode() === 429) { // Rate limited - wait and retry $retries++; sleep(5); continue; } elseif ($e->getCode() >= 500) { // Server error - exponential backoff $retries++; $delay = pow(2, $retries); sleep($delay); if ($retries >= $maxRetries) { throw $e; } continue; } else { // Other errors - don't retry throw $e; } } } throw new Exception("Max retries exceeded"); } // Usage $request = new DiffusionRequest(); $request->setText('a beautiful landscape'); try { $response = callWithRetry($imageApi, $request, 3); echo "Job ID: " . $response->getJobId() . "\n"; } catch (Exception $e) { echo "Failed after retries: " . $e->getMessage() . "\n"; } ?> ``` --- ## Processing Multiple Tasks For processing multiple tasks sequentially: ```php setText($prompt); $response = $imageApi->generateImage($request); $jobId = $response->getJobId(); echo "Started job for '{$prompt}': {$jobId}\n"; // Wait for completion $result = waitForCompletion($taskApi, $jobId, 600, 3); $output = $result->getOutput(); if ($output !== null && $output->getImageUrls() !== null && count($output->getImageUrls()) > 0) { $results[] = [ 'prompt' => $prompt, 'url' => $output->getImageUrls()[0] ]; } } catch (Exception $e) { $results[] = [ 'prompt' => $prompt, 'error' => $e->getMessage() ]; } } return $results; } // Usage $prompts = ['sunset', 'mountains', 'ocean']; $results = generateMultipleImages($imageApi, $taskApi, $prompts); foreach ($results as $result) { if (isset($result['error'])) { echo "Error for '{$result['prompt']}': {$result['error']}\n"; } else { echo "Image '{$result['prompt']}': {$result['url']}\n"; } } ?> ``` --- ## Progress Callbacks ```php getTaskStatus($jobId); // Call progress callback if ($onProgress !== null) { $progress = $task->getProgress() ?? 0; $status = $task->getStatus() ?? 'unknown'; call_user_func($onProgress, $progress, $status); } if ($task->getStatus() === 'completed') { return $task; } elseif ($task->getStatus() === 'failed') { throw new Exception("Task failed: " . $task->getError()); } $elapsed = time() - $startTime; if ($elapsed > $timeoutSeconds) { throw new Exception("Task timeout after {$timeoutSeconds} seconds"); } sleep($pollIntervalSeconds); } } // Usage $result = waitForCompletionWithProgress( $taskApi, $jobId, function($progress, $status) { echo "Progress: {$progress}% - Status: {$status}\n"; }, 600, 3 ); ?> ``` --- ## Laravel Integration For Laravel applications, create a service class: ```php setApiKey('x-api-key', config('legnext.api_key')); $config->setHost(config('legnext.host')); $this->imageApi = new ImageGenerationApi(null, $config); $this->taskApi = new TaskManagementApi(null, $config); } public function generateImage($text, $callback = null) { $request = new DiffusionRequest(); $request->setText($text); if ($callback !== null) { $request->setCallback($callback); } return $this->imageApi->generateImage($request); } public function getTaskStatus($jobId) { return $this->taskApi->getTaskStatus($jobId); } public function waitForCompletion($jobId, $timeoutSeconds = 300, $pollIntervalSeconds = 3) { $startTime = time(); while (true) { $task = $this->getTaskStatus($jobId); if ($task->getStatus() === 'completed') { return $task; } elseif ($task->getStatus() === 'failed') { throw new \Exception("Task failed: " . $task->getError()); } $elapsed = time() - $startTime; if ($elapsed > $timeoutSeconds) { throw new \Exception("Task timeout after {$timeoutSeconds} seconds"); } sleep($pollIntervalSeconds); } } } ?> ``` **Usage in Controller:** ```php legnext = $legnext; } public function generate(Request $request) { try { $text = $request->input('text'); $response = $this->legnext->generateImage($text); return response()->json([ 'job_id' => $response->getJobId(), 'status' => $response->getStatus() ]); } catch (\Exception $e) { return response()->json(['error' => $e->getMessage()], 500); } } public function status($jobId) { try { $task = $this->legnext->getTaskStatus($jobId); return response()->json([ 'status' => $task->getStatus(), 'progress' => $task->getProgress(), 'output' => $task->getOutput() ]); } catch (\Exception $e) { return response()->json(['error' => $e->getMessage()], 500); } } } ?> ``` --- ## Learn More - [Image Generation API](https://docs.legnext.ai/sdk/php/image-generation) - [Video Generation API](https://docs.legnext.ai/sdk/php/video-generation) - [Quick Start](https://docs.legnext.ai/sdk/php/quickstart) --- # Installation _Install the Legnext Ruby SDK_ ## Requirements - **Ruby**: Version 2.7 or higher - **Bundler**: Latest version ## Install via RubyGems ```bash gem install legnext-sdk ``` ## Install via Bundler Add this to your `Gemfile`: ```ruby gem 'legnext-sdk', '~> 1.0.0' ``` Then run: ```bash bundle install ``` ## Verify Installation ```bash gem list legnext-sdk ``` --- # Authentication _Set up API authentication for Ruby SDK_ ## Getting Your API Key 1. Visit [Legnext.ai Dashboard](https://legnext.ai/dashboard) 2. Navigate to API Keys section 3. Generate a new API key 4. Copy and store securely ## Authentication Methods ### Method 1: Environment Variables (Recommended) Set your API key as an environment variable: ```bash export LEGNEXT_API_KEY="your-api-key-here" ``` Then use it in your Ruby code: ```ruby require 'openapi_client' # Configure API client OpenapiClient.configure do |config| config.api_key['x-api-key'] = ENV['LEGNEXT_API_KEY'] config.host = 'api.legnext.ai' config.base_path = '' end # Create API instance api = OpenapiClient::ImageApi.new # Now you can use the API # ... ``` ### Method 2: Direct Initialization Hardcode the API key directly (not recommended for production): ```ruby require 'openapi_client' OpenapiClient.configure do |config| config.api_key['x-api-key'] = 'your-api-key-here' config.host = 'api.legnext.ai' config.base_path = '' end api = OpenapiClient::ImageApi.new ``` ### Method 3: Using dotenv Gem Use the `dotenv` gem to load from `.env` files: ```bash gem install dotenv ``` ```ruby require 'dotenv/load' require 'openapi_client' # .env file is automatically loaded OpenapiClient.configure do |config| config.api_key['x-api-key'] = ENV['LEGNEXT_API_KEY'] config.host = 'api.legnext.ai' config.base_path = '' end api = OpenapiClient::ImageApi.new ``` **.env file:** ``` LEGNEXT_API_KEY=your-api-key-here ``` ### Method 4: YAML Configuration File Load API key from a YAML configuration file: ```ruby require 'yaml' require 'openapi_client' # Load configuration config_file = YAML.load_file('config.yml') OpenapiClient.configure do |config| config.api_key['x-api-key'] = config_file['api_key'] config.host = 'api.legnext.ai' config.base_path = '' end api = OpenapiClient::ImageApi.new ``` **config.yml:** ```yaml api_key: your-api-key-here environment: development ``` ### Method 5: Rails Credentials (for Rails Applications) For Rails 5.2+, use encrypted credentials: ```bash rails credentials:edit ``` Add to credentials: ```yaml legnext: api_key: your-api-key-here ``` In your Rails app: ```ruby require 'openapi_client' OpenapiClient.configure do |config| config.api_key['x-api-key'] = Rails.application.credentials.legnext[:api_key] config.host = 'api.legnext.ai' config.base_path = '' end api = OpenapiClient::ImageApi.new ``` --- ## Complete Configuration Example ```ruby require 'openapi_client' OpenapiClient.configure do |config| # Required: API Key config.api_key['x-api-key'] = ENV['LEGNEXT_API_KEY'] # Required: API Host config.host = 'api.legnext.ai' config.base_path = '' # Optional: Set debugging mode config.debugging = ENV['LEGNEXT_DEBUG'] == 'true' # Optional: Set timeout (in seconds) config.timeout = 120 # Optional: Set custom user agent config.user_agent = 'MyApp/1.0' # Optional: SSL verification (recommended: true) config.verify_ssl = true config.verify_ssl_host = true end ``` --- ## Security Best Practices 1. **Never commit API keys to version control** ```ruby # .gitignore .env config.yml config/credentials/*.yml.enc ``` 2. **Use environment variables in production** ```bash # Set in your deployment environment export LEGNEXT_API_KEY="your-production-key" ``` 3. **Rotate keys regularly** - Generate new keys periodically - Revoke old keys after rotation 4. **Use different keys for development and production** ```ruby OpenapiClient.configure do |config| api_key = if ENV['RAILS_ENV'] == 'production' ENV['LEGNEXT_PROD_API_KEY'] else ENV['LEGNEXT_DEV_API_KEY'] end config.api_key['x-api-key'] = api_key config.host = 'api.legnext.ai' config.base_path = '' end ``` 5. **Restrict API key permissions** - Use the minimum required permissions - Monitor usage through the dashboard 6. **Enable SSL verification** ```ruby OpenapiClient.configure do |config| config.verify_ssl = true config.verify_ssl_host = true end ``` --- ## Testing Authentication Verify your API key is working: ```ruby require 'openapi_client' OpenapiClient.configure do |config| config.api_key['x-api-key'] = ENV['LEGNEXT_API_KEY'] config.host = 'api.legnext.ai' config.base_path = '' end api_key = ENV['LEGNEXT_API_KEY'] account_api = OpenapiClient::AccountManagementApi.new begin # Test with account balance endpoint response = account_api.api_account_balance_get({x_api_key: api_key}) puts "✅ Authentication successful!" if response.data puts "Balance: $#{response.data.balance_usd}" end rescue OpenapiClient::ApiError => e if e.code == 401 puts "❌ Authentication failed: Invalid API key" else puts "❌ Error: #{e.message}" end end ``` --- ## Debugging Enable debugging to see HTTP requests and responses: ```ruby OpenapiClient.configure do |config| config.api_key['x-api-key'] = ENV['LEGNEXT_API_KEY'] config.host = 'api.legnext.ai' config.base_path = '' config.debugging = true # Enable debug output config.logger = Logger.new(STDOUT) # Custom logger config.logger.level = Logger::DEBUG end ``` --- ## Next Steps - [Image Generation](https://docs.legnext.ai/sdk/ruby/image-generation) - [Video Generation](https://docs.legnext.ai/sdk/ruby/video-generation) - [Task Management](https://docs.legnext.ai/sdk/ruby/task-management) - [Quick Start](https://docs.legnext.ai/sdk/ruby/quickstart) --- # Quick Start _Get started with the Legnext Ruby SDK_ ## 1. Install ```bash gem install legnext-ruby-sdk ``` ## 2. Set API Key ```bash export LEGNEXT_API_KEY="your-api-key" ``` ## 3. Basic Example ```ruby require 'openapi_client' # Configure API client OpenapiClient.configure do |config| config.api_key['x-api-key'] = ENV['LEGNEXT_API_KEY'] config.host = 'api.legnext.ai' config.base_path = '' end # Create API instance api = OpenapiClient::ImageApi.new begin # Generate image request = { text: 'a beautiful sunset over mountains' } response = api.api_v1_diffusion_post(request) puts "Response: #{response}" rescue OpenapiClient::ApiError => e puts "Error: #{e.message}" end ``` ## 4. Check Task Status ```ruby video_api = OpenapiClient::VideoApi.new begin task_response = video_api.api_v1_job_job_id_get(job_id) puts "Status: #{task_response.status}" if task_response.output puts "Images: #{task_response.output.image_urls}" end rescue OpenapiClient::ApiError => e puts "Error: #{e.message}" end ``` ## Error Handling ```ruby begin response = api.api_v1_diffusion_post(request) rescue OpenapiClient::ApiError => e puts "HTTP Status: #{e.code}" puts "Error Message: #{e.message}" puts "Response Body: #{e.response_body}" puts "Response Headers: #{e.response_headers}" end ``` ## Available APIs - `ImageApi` - Text to image, variations, upscaling, editing - `VideoApi` - Video generation, upscaling, and task status - `AccountManagementApi` - Account balance and information --- # Image Generation _Image generation API reference for Ruby SDK_ ## generate_image() Create a new text-to-image generation task. ```ruby require 'legnext_sdk' # Configure API client Legnext.configure do |config| config.api_key['x-api-key'] = ENV['LEGNEXT_API_KEY'] config.host = 'api.legnext.ai' config.base_path = '/api' end api = Legnext::ImageGenerationApi.new begin request = Legnext::DiffusionRequest.new( text: 'a serene mountain landscape at sunset', callback: 'https://your-domain.com/webhook' ) response = api.generate_image(request) puts "Job ID: #{response.job_id}" puts "Status: #{response.status}" rescue Legnext::ApiError => e puts "Error: #{e.message}" end ``` **Parameters:** - `text` (String): Text prompt (1-8192 characters) - `callback` (String, optional): Webhook URL for completion notification **Returns:** Response with `job_id` and `status` --- ## vary_image() Create variations of a generated image. ```ruby request = Legnext::VaryRequest.new( job_id: 'original-job-id', image_no: 0, type: 1, # 0=Subtle, 1=Strong remix_prompt: 'add more clouds' ) response = api.vary_image(request) puts "Variation Job ID: #{response.job_id}" ``` **Parameters:** - `job_id` (String): Original image job ID - `image_no` (Integer): Image index (0-3) - `type` (Integer): Variation type (0=Subtle, 1=Strong) - `remix_prompt` (String, optional): Additional prompt for variation --- ## upscale_image() Upscale a generated image to higher resolution. ```ruby request = Legnext::UpscaleRequest.new( job_id: 'original-job-id', image_no: 0, type: 1 # 0=Subtle, 1=Creative ) response = api.upscale_image(request) puts "Upscale Job ID: #{response.job_id}" ``` **Parameters:** - `job_id` (String): Original image job ID - `image_no` (Integer): Image index (0-3) - `type` (Integer): Upscale type (0=Subtle, 1=Creative) --- ## reroll_image() Regenerate with the same prompt. ```ruby request = Legnext::RerollRequest.new( job_id: 'original-job-id' ) response = api.reroll_image(request) puts "Reroll Job ID: #{response.job_id}" ``` **Parameters:** - `job_id` (String): Original image job ID --- ## blend_images() Blend 2-5 images together. ```ruby request = Legnext::BlendRequest.new( img_urls: [ 'https://example.com/image1.png', 'https://example.com/image2.png' ], aspect_ratio: '1:1' # Options: 1:1, 16:9, 9:16, 3:2, 2:3 ) response = api.blend_images(request) puts "Blend Job ID: #{response.job_id}" ``` **Parameters:** - `img_urls` (Array): Array of 2-5 image URLs - `aspect_ratio` (String, optional): Output aspect ratio (1:1, 16:9, 9:16, 3:2, 2:3) --- ## describe_image() Generate text descriptions from an image. ```ruby request = Legnext::DescribeRequest.new( img_url: 'https://example.com/image.png' ) response = api.describe_image(request) puts "Describe Job ID: #{response.job_id}" ``` **Parameters:** - `img_url` (String): URL of the image to describe --- ## edit_image() Edit an image with text description. ```ruby request = Legnext::EditRequest.new( job_id: 'original-job-id', image_no: 0, canvas: 'original', # Canvas to edit img_pos: 0, # Image position remix_prompt: 'change the sky to sunset colors', callback: 'https://your-domain.com/webhook' ) response = api.edit_image(request) puts "Edit Job ID: #{response.job_id}" ``` **Parameters:** - `job_id` (String): Original image job ID - `image_no` (Integer): Image index (0-3) - `canvas` (String): Canvas to edit - `img_pos` (Integer): Image position - `remix_prompt` (String): Edit instructions - `callback` (String, optional): Webhook URL --- ## inpaint_image() Fill masked regions in an image. ```ruby request = Legnext::InpaintRequest.new( job_id: 'original-job-id', image_no: 0, remix_prompt: 'fill with forest landscape', mask: { type: 'url', value: 'https://example.com/mask.png' }, callback: 'https://your-domain.com/webhook' ) response = api.inpaint_image(request) puts "Inpaint Job ID: #{response.job_id}" ``` **Parameters:** - `job_id` (String): Original image job ID - `image_no` (Integer): Image index (0-3) - `remix_prompt` (String): Inpainting prompt - `mask` (Hash): Mask structure with `type` and `value` - `callback` (String, optional): Webhook URL --- ## outpaint_image() Extend image boundaries. ```ruby request = Legnext::OutpaintRequest.new( job_id: 'original-job-id', image_no: 0, scale: 1.5, # Scale factor (1.1-3.0) remix_prompt: 'extend with matching scenery', callback: 'https://your-domain.com/webhook' ) response = api.outpaint_image(request) puts "Outpaint Job ID: #{response.job_id}" ``` **Parameters:** - `job_id` (String): Original image job ID - `image_no` (Integer): Image index (0-3) - `scale` (Float): Scale factor for extension (1.1-3.0) - `remix_prompt` (String, optional): Additional prompt for outpainting - `callback` (String, optional): Webhook URL --- ## pan_image() Create panoramic or panned views. ```ruby request = Legnext::PanRequest.new( job_id: 'original-job-id', image_no: 0, direction: 3, # Direction (0=Down, 1=Right, 2=Up, 3=Left) scale: 1.5, # Scale factor (1.1-3.0) remix_prompt: 'continue the landscape naturally', callback: 'https://your-domain.com/webhook' ) response = api.pan_image(request) puts "Pan Job ID: #{response.job_id}" ``` **Parameters:** - `job_id` (String): Original image job ID - `image_no` (Integer): Image index (0-3) - `direction` (Integer): Pan direction (0=Down, 1=Right, 2=Up, 3=Left) - `scale` (Float): Scale factor (1.1-3.0) - `remix_prompt` (String, optional): Additional prompt for panning - `callback` (String, optional): Webhook URL --- ## remix_image() Apply a remix effect to an image with different intensity. ```ruby request = Legnext::RemixRequest.new( job_id: 'original-job-id', image_no: 0, mode: 0, # Mode (0=Strong, 1=Subtle) remix_prompt: 'adjust colors and lighting', callback: 'https://your-domain.com/webhook' ) response = api.remix_image(request) puts "Remix Job ID: #{response.job_id}" ``` **Parameters:** - `job_id` (String): Original image job ID - `image_no` (Integer): Image index (0-3) - `mode` (Integer): Remix mode (0=Strong, 1=Subtle) - `remix_prompt` (String, optional): Additional prompt for remix - `callback` (String, optional): Webhook URL --- ## shorten_prompt() Optimize and simplify prompts. ```ruby request = Legnext::ShortenRequest.new( prompt: 'your very long and detailed prompt here with lots of unnecessary words and descriptions that could be made more concise...' ) response = api.shorten_prompt(request) puts "Shortened prompt: #{response.shortened_prompt}" ``` **Parameters:** - `prompt` (String): Long prompt to optimize **Returns:** Response with `shortened_prompt` --- ## Complete Example ```ruby require 'legnext_sdk' # Configure API client Legnext.configure do |config| config.api_key['x-api-key'] = ENV['LEGNEXT_API_KEY'] config.host = 'api.legnext.ai' config.base_path = '/api' end api = Legnext::ImageGenerationApi.new begin # Step 1: Generate image request = Legnext::DiffusionRequest.new( text: 'a beautiful sunset over mountains', callback: 'https://your-domain.com/webhook' ) response = api.generate_image(request) job_id = response.job_id puts "Image generation started: #{job_id}" # Step 2: Wait for completion (see Task Management docs) # ... # Step 3: Upscale the first image upscale_request = Legnext::UpscaleRequest.new( job_id: job_id, image_no: 0, type: 1, callback: 'https://your-domain.com/webhook' ) upscale_response = api.upscale_image(upscale_request) puts "Upscale started: #{upscale_response.job_id}" rescue Legnext::ApiError => e puts "HTTP Status: #{e.code}" puts "Error Message: #{e.message}" puts "Response Body: #{e.response_body}" end ``` --- ## Error Handling ```ruby begin response = api.generate_image(request) rescue Legnext::ApiError => e case e.code when 400 puts "Validation error: Check request parameters" when 401 puts "Authentication error: Invalid API key" when 404 puts "Resource not found" when 429 puts "Rate limit exceeded. Please retry later." when 500, 502, 503 puts "Server error. Please retry." else puts "API error (#{e.code}): #{e.message}" end puts "Response body: #{e.response_body}" end ``` --- ## Using Blocks Ruby idiomatic way with blocks: ```ruby require 'legnext_sdk' Legnext.configure do |config| config.api_key['x-api-key'] = ENV['LEGNEXT_API_KEY'] config.host = 'api.legnext.ai' config.base_path = '/api' end def generate_with_retry(api, request, max_retries = 3) retries = 0 begin api.generate_image(request) rescue Legnext::ApiError => e if e.code == 429 && retries < max_retries retries += 1 sleep 5 retry elsif e.code >= 500 && retries < max_retries retries += 1 sleep(2**retries) retry else raise end end end api = Legnext::ImageGenerationApi.new request = Legnext::DiffusionRequest.new( text: 'a beautiful landscape', callback: 'https://your-domain.com/webhook' ) response = generate_with_retry(api, request) puts "Job ID: #{response.job_id}" ``` --- ## Next Steps - [Video Generation](https://docs.legnext.ai/sdk/ruby/video-generation) - [Task Management](https://docs.legnext.ai/sdk/ruby/task-management) - [Quick Start](https://docs.legnext.ai/sdk/ruby/quickstart) --- # Video Generation _Video generation API reference for Ruby SDK_ ## generate_video() Generate a video from text prompt with optional image URL. ```ruby require 'legnext_sdk' # Configure API client Legnext.configure do |config| config.api_key['x-api-key'] = ENV['LEGNEXT_API_KEY'] config.host = 'api.legnext.ai' config.base_path = '/api' end api = Legnext::VideoGenerationApi.new begin # Mode 1: Generate from text only request = Legnext::VideoDiffusionRequest.new( prompt: 'a flowing river through mountains', video_type: 1, # 0=480p, 1=720p callback: 'https://your-domain.com/webhook' ) response = api.generate_video(request) puts "Job ID: #{response.job_id}" puts "Status: #{response.status}" rescue Legnext::ApiError => e puts "Error: #{e.message}" end ``` **Mode 2: Generate from image URL in prompt:** ```ruby # Generate video from image included in prompt request = Legnext::VideoDiffusionRequest.new( prompt: 'https://example.com/image.png a flowing river through mountains', video_type: 1, callback: 'https://your-domain.com/webhook' ) response = api.generate_video(request) puts "Job ID: #{response.job_id}" ``` **Mode 3: Animate existing image:** ```ruby # Animate an image from a previous generation job request = Legnext::VideoDiffusionRequest.new( job_id: 'previous-image-job-id', image_no: 0, prompt: 'flowing movement through the landscape', video_type: 1, callback: 'https://your-domain.com/webhook' ) response = api.generate_video(request) puts "Job ID: #{response.job_id}" ``` **Parameters:** - `prompt` (String): Video prompt or "[image_url] prompt text" (1-8192 characters) - `job_id` (String, optional): Original image job ID (for image animation mode) - `image_no` (Integer, optional): Image index (0-3) (for image animation mode) - `video_type` (Integer, optional): Quality (0=480p, 1=720p) - `callback` (String, optional): Webhook URL **Returns:** Response with `job_id` and `status` --- ## extend_video() Extend an existing video. ```ruby request = Legnext::ExtendVideoRequest.new( job_id: 'original-video-job-id', video_no: 0, prompt: 'continue with dramatic lighting', callback: 'https://your-domain.com/webhook' ) response = api.extend_video(request) puts "Extension Job ID: #{response.job_id}" ``` **Parameters:** - `job_id` (String): Original video task ID - `video_no` (Integer): Video index (0-3) - `prompt` (String, optional): Extension prompt (1-8192 characters) - `callback` (String, optional): Webhook URL **Returns:** Response with `job_id` and `status` --- ## upscale_video() Upscale video to higher resolution. ```ruby request = Legnext::VideoUpscaleRequest.new( job_id: 'original-video-job-id', video_no: 0, callback: 'https://your-domain.com/webhook' ) response = api.upscale_video(request) puts "Upscale Job ID: #{response.job_id}" ``` **Parameters:** - `job_id` (String): Original video task ID - `video_no` (Integer): Video index (0-3) - `callback` (String, optional): Webhook URL **Returns:** Response with `job_id` and `status` --- ## Complete Example ```ruby require 'legnext_sdk' # Configure API client Legnext.configure do |config| config.api_key['x-api-key'] = ENV['LEGNEXT_API_KEY'] config.host = 'api.legnext.ai' config.base_path = '/api' end api = Legnext::VideoGenerationApi.new begin # Step 1: Generate video request = Legnext::VideoDiffusionRequest.new( prompt: 'a beautiful sunset over the ocean', video_type: 1, callback: 'https://your-domain.com/webhook' ) response = api.generate_video(request) job_id = response.job_id puts "Video generation started: #{job_id}" # Step 2: Wait for completion (see Task Management docs) # ... # Step 3: Extend the video extend_request = Legnext::ExtendVideoRequest.new( job_id: job_id, video_no: 0, prompt: 'continue with dramatic clouds', callback: 'https://your-domain.com/webhook' ) extend_response = api.extend_video(extend_request) puts "Video extension started: #{extend_response.job_id}" # Step 4: Upscale the extended video upscale_request = Legnext::VideoUpscaleRequest.new( job_id: extend_response.job_id, video_no: 0, callback: 'https://your-domain.com/webhook' ) upscale_response = api.upscale_video(upscale_request) puts "Video upscale started: #{upscale_response.job_id}" rescue Legnext::ApiError => e puts "HTTP Status: #{e.code}" puts "Error Message: #{e.message}" puts "Response Body: #{e.response_body}" end ``` --- ## Error Handling ```ruby begin response = api.generate_video(request) rescue Legnext::ApiError => e case e.code when 400 puts "Validation error: Check request parameters" when 401 puts "Authentication error: Invalid API key" when 404 puts "Resource not found" when 429 puts "Rate limit exceeded. Please retry later." when 500, 502, 503 puts "Server error. Please retry." else puts "API error (#{e.code}): #{e.message}" end puts "Response body: #{e.response_body}" end ``` --- ## Retry Logic ```ruby def generate_video_with_retry(api, request, max_retries = 3) retries = 0 begin api.generate_video(request) rescue Legnext::ApiError => e if e.code == 429 && retries < max_retries # Rate limited - wait and retry retries += 1 sleep 5 retry elsif e.code >= 500 && retries < max_retries # Server error - exponential backoff retries += 1 sleep(2**retries) retry else # Other errors - don't retry raise end end end # Usage api = Legnext::VideoGenerationApi.new request = Legnext::VideoDiffusionRequest.new( prompt: 'a flowing river', video_type: 1, callback: 'https://your-domain.com/webhook' ) response = generate_video_with_retry(api, request) puts "Job ID: #{response.job_id}" ``` --- ## Asynchronous Processing with Threads ```ruby require 'thread' def process_multiple_videos(api, prompts) threads = [] results = Queue.new prompts.each do |prompt| threads << Thread.new do begin request = Legnext::VideoDiffusionRequest.new( prompt: prompt, video_type: 1, callback: 'https://your-domain.com/webhook' ) response = api.generate_video(request) results << { prompt: prompt, job_id: response.job_id } rescue Legnext::ApiError => e results << { prompt: prompt, error: e.message } end end end # Wait for all threads threads.each(&:join) # Collect results all_results = [] all_results << results.pop until results.empty? all_results end # Usage api = Legnext::VideoGenerationApi.new prompts = ['sunset', 'mountains', 'ocean'] results = process_multiple_videos(api, prompts) results.each do |result| if result[:error] puts "Error for '#{result[:prompt]}': #{result[:error]}" else puts "Video '#{result[:prompt]}': #{result[:job_id]}" end end ``` --- ## Next Steps - [Image Generation](https://docs.legnext.ai/sdk/ruby/image-generation) - [Task Management](https://docs.legnext.ai/sdk/ruby/task-management) - [Quick Start](https://docs.legnext.ai/sdk/ruby/quickstart) --- # Task Management _Task status, polling, and error handling for Ruby SDK_ ## get_task_status() Get current task status: ```ruby require 'legnext_sdk' # Configure API client Legnext.configure do |config| config.api_key['x-api-key'] = ENV['LEGNEXT_API_KEY'] config.host = 'api.legnext.ai' config.base_path = '/api' end task_api = Legnext::TaskManagementApi.new begin job_id = 'job-123' task = task_api.get_task_status(job_id) puts "Status: #{task.status}" puts "Progress: #{task.progress}%" if task.status == 'completed' puts "Result: #{task.output}" end rescue Legnext::ApiError => e puts "Error: #{e.message}" end ``` --- ## Polling for Completion Wait for task completion with polling: ```ruby def wait_for_completion(task_api, job_id, timeout_seconds = 300, poll_interval_seconds = 3) start_time = Time.now timeout = timeout_seconds loop do task = task_api.get_task_status(job_id) puts "Current status: #{task.status}" if task.status == 'completed' puts "Task completed successfully!" puts "Output: #{task.output}" return task elsif task.status == 'failed' raise "Task failed: #{task.error}" end # Check timeout elapsed = Time.now - start_time if elapsed > timeout raise "Task timeout after #{timeout_seconds} seconds" end # Wait before next poll sleep poll_interval_seconds end end ``` **Usage:** ```ruby task_api = Legnext::TaskManagementApi.new job_id = 'job-123' begin result = wait_for_completion(task_api, job_id, 300, 3) puts "Final result: #{result}" rescue StandardError => e puts "Error: #{e.message}" end ``` --- ## Complete Example with Error Handling ```ruby require 'legnext_sdk' # Configure API client Legnext.configure do |config| config.api_key['x-api-key'] = ENV['LEGNEXT_API_KEY'] config.host = 'api.legnext.ai' config.base_path = '/api' end def wait_for_completion(task_api, job_id, timeout_seconds = 300, poll_interval_seconds = 3) start_time = Time.now timeout = timeout_seconds loop do task = task_api.get_task_status(job_id) if task.status == 'completed' return task elsif task.status == 'failed' raise "Task failed: #{task.error}" end elapsed = Time.now - start_time if elapsed > timeout raise "Task timeout after #{timeout_seconds} seconds" end sleep poll_interval_seconds end end def generate_image_with_polling image_api = Legnext::ImageGenerationApi.new task_api = Legnext::TaskManagementApi.new # Step 1: Start generation request = Legnext::DiffusionRequest.new( text: 'a beautiful sunset over mountains' ) response = image_api.generate_image(request) job_id = response.job_id puts "Job started: #{job_id}" # Step 2: Poll for completion result = wait_for_completion(task_api, job_id, 600, 3) # Step 3: Get final result if result.output && result.output.image_urls puts "Image URLs: #{result.output.image_urls}" end rescue Legnext::ApiError => e handle_api_error(e) rescue StandardError => e puts "Error: #{e.message}" end def handle_api_error(error) case error.code when 400 puts "Validation error: #{error.response_body}" when 401 puts "Authentication error: Invalid API key" when 404 puts "Resource not found: #{error.response_body}" when 429 puts "Rate limit exceeded. Please retry later." when 500, 502, 503 puts "Server error: #{error.response_body}" else puts "API error (#{error.code}): #{error.response_body}" end end generate_image_with_polling ``` --- ## Error Handling **HTTP Error Handling:** ```ruby begin task = task_api.get_task_status(job_id) rescue Legnext::ApiError => e case e.code when 400 puts "Validation error: Check request parameters" when 401 puts "Authentication error: Invalid API key" when 404 puts "Resource not found: Check job ID exists" when 429 puts "Rate limit exceeded. Please retry later." when 500, 502, 503 puts "Server error. Please retry with backoff." else puts "API error (#{e.code}): #{e.message}" end puts "Response body: #{e.response_body}" end ``` **Common HTTP Status Codes:** | Status Code | Description | Action | |-------------|-------------|--------| | 400 | Invalid request parameters | Check request body format | | 401 | Invalid API key | Verify API key is correct | | 404 | Resource not found | Check job ID exists | | 429 | Rate limit exceeded | Wait and retry with backoff | | 500/502/503 | Server error | Retry with exponential backoff | **Retry Logic with Exponential Backoff:** ```ruby def call_with_retry(image_api, request, max_retries = 3) retries = 0 begin image_api.generate_image(request) rescue Legnext::ApiError => e if e.code == 429 && retries < max_retries # Rate limited - wait and retry retries += 1 sleep 5 retry elsif e.code >= 500 && retries < max_retries # Server error - exponential backoff retries += 1 delay = 2**retries sleep delay retry if retries < max_retries raise else # Other errors - don't retry raise end end end # Usage image_api = Legnext::ImageGenerationApi.new request = Legnext::DiffusionRequest.new(text: 'a beautiful landscape') begin response = call_with_retry(image_api, request, 3) puts "Job ID: #{response.job_id}" rescue Legnext::ApiError => e puts "Failed after retries: #{e.message}" end ``` --- ## Concurrent Operations with Threads For processing multiple tasks concurrently: ```ruby require 'thread' def generate_multiple_images Legnext.configure do |config| config.api_key['x-api-key'] = ENV['LEGNEXT_API_KEY'] config.host = 'api.legnext.ai' config.base_path = '/api' end image_api = Legnext::ImageGenerationApi.new task_api = Legnext::TaskManagementApi.new prompts = ['sunset', 'mountains', 'ocean'] threads = [] results = Queue.new prompts.each do |prompt| threads << Thread.new do begin # Start generation request = Legnext::DiffusionRequest.new(text: prompt) response = image_api.generate_image(request) job_id = response.job_id # Wait for completion result = wait_for_completion(task_api, job_id, 600, 3) if result.output && result.output.image_urls && !result.output.image_urls.empty? results << { prompt: prompt, url: result.output.image_urls[0] } end rescue StandardError => e results << { prompt: prompt, error: e.message } end end end # Wait for all threads threads.each(&:join) # Collect results all_results = [] all_results << results.pop until results.empty? all_results.each do |result| if result[:error] puts "Error for '#{result[:prompt]}': #{result[:error]}" else puts "Image '#{result[:prompt]}': #{result[:url]}" end end end generate_multiple_images ``` --- ## Progress Callbacks ```ruby def wait_for_completion_with_progress(task_api, job_id, timeout_seconds = 300, poll_interval_seconds = 3, &block) start_time = Time.now timeout = timeout_seconds loop do task = task_api.get_task_status(job_id) # Call progress callback if block_given? progress = task.progress || 0 status = task.status || 'unknown' yield(progress, status) end if task.status == 'completed' return task elsif task.status == 'failed' raise "Task failed: #{task.error}" end elapsed = Time.now - start_time if elapsed > timeout raise "Task timeout after #{timeout_seconds} seconds" end sleep poll_interval_seconds end end # Usage task_api = Legnext::TaskManagementApi.new job_id = 'job-123' result = wait_for_completion_with_progress(task_api, job_id, 600, 3) do |progress, status| puts "Progress: #{progress}% - Status: #{status}" end ``` --- ## Using Fibers for Cooperative Multitasking ```ruby require 'fiber' def create_image_fiber(image_api, task_api, prompt) Fiber.new do # Start generation request = Legnext::DiffusionRequest.new(text: prompt) response = image_api.generate_image(request) job_id = response.job_id Fiber.yield job_id # Poll for completion loop do task = task_api.get_task_status(job_id) if task.status == 'completed' Fiber.yield task.output break elsif task.status == 'failed' raise "Task failed: #{task.error}" end Fiber.yield :pending sleep 3 end end end # Usage Legnext.configure do |config| config.api_key['x-api-key'] = ENV['LEGNEXT_API_KEY'] config.host = 'api.legnext.ai' config.base_path = '/api' end image_api = Legnext::ImageGenerationApi.new task_api = Legnext::TaskManagementApi.new fiber = create_image_fiber(image_api, task_api, 'a beautiful landscape') job_id = fiber.resume puts "Job started: #{job_id}" loop do result = fiber.resume break unless fiber.alive? if result == :pending puts "Still processing..." elsif result puts "Result: #{result}" end end ``` --- ## Learn More - [Image Generation API](https://docs.legnext.ai/sdk/ruby/image-generation) - [Video Generation API](https://docs.legnext.ai/sdk/ruby/video-generation) - [Quick Start](https://docs.legnext.ai/sdk/ruby/quickstart) --- # Installation _Install the Legnext C#/.NET SDK_ ## Requirements - **.NET**: Version 6.0 or higher (or .NET Framework 4.6.2+) - **NuGet**: Package manager ## Install via NuGet ### Using Package Manager Console ```powershell Install-Package Legnext.SDK ``` ### Using .NET CLI ```bash dotnet add package Legnext.SDK ``` ### Using Package Reference Add to your `.csproj` file: ```xml ``` ## Verify Installation ```bash dotnet list package | grep Legnext ``` --- # Authentication _Set up API authentication for C#/.NET SDK_ ## Getting Your API Key 1. Visit [Legnext.ai Dashboard](https://legnext.ai/dashboard) 2. Navigate to API Keys section 3. Generate a new API key 4. Copy and store securely ## Authentication Methods ### Method 1: Environment Variables (Recommended) Set your API key as an environment variable: ```bash export LEGNEXT_API_KEY="your-api-key-here" ``` Then use it in your C# code: ```csharp using System; using Microsoft.Extensions.DependencyInjection; using Legnext.SDK.Api; using Legnext.SDK.Client; using Legnext.SDK.Extensions; string apiKey = Environment.GetEnvironmentVariable("LEGNEXT_API_KEY"); var services = new ServiceCollection(); services.AddApi(config => { config.AddApiHttpClients(client => { client.BaseAddress = new Uri("https://api.legnext.ai"); }); }); var provider = services.BuildServiceProvider(); var imageApi = provider.GetRequiredService(); // Use imageApi with apiKey in method calls var response = await imageApi.ApiV1DiffusionPostAsync( new Option(apiKey), request ); ``` ### Method 2: appsettings.json Configuration For ASP.NET Core applications: **appsettings.json:** ```json { "Legnext": { "ApiKey": "your-api-key-here", "BaseUrl": "https://api.legnext.ai" } } ``` **Usage:** ```csharp string apiKey = Configuration["Legnext:ApiKey"]; string baseUrl = Configuration["Legnext:BaseUrl"]; ``` ### Method 3: User Secrets (Development) For development environments: ```bash dotnet user-secrets init dotnet user-secrets set "Legnext:ApiKey" "your-api-key-here" ``` Then access in code: ```csharp string apiKey = Configuration["Legnext:ApiKey"]; ``` --- ## Complete Setup Example ```csharp using System; using System.Text.Json; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Legnext.SDK.Api; using Legnext.SDK.Client; using Legnext.SDK.Extensions; public class LegnextService { private readonly IServiceProvider _serviceProvider; private readonly string _apiKey; public LegnextService(string apiKey) { _apiKey = apiKey; var services = new ServiceCollection(); services.AddApi(config => { config.AddApiHttpClients(client => { client.BaseAddress = new Uri("https://api.legnext.ai"); client.Timeout = TimeSpan.FromMinutes(5); }); }); _serviceProvider = services.BuildServiceProvider(); } public async Task GenerateImageAsync(string prompt) { var imageApi = _serviceProvider.GetRequiredService(); var request = new Dictionary { { "text", prompt } }; var response = await imageApi.ApiV1DiffusionPostAsync( new Option(_apiKey), request ); if (response.IsOk) { var jsonDoc = JsonDocument.Parse(response.RawContent); if (jsonDoc.RootElement.TryGetProperty("job_id", out var jobId)) { return jobId.GetString(); } } throw new Exception("Failed to generate image"); } } ``` --- ## Security Best Practices 1. **Never hardcode API keys** 2. **Use different keys for different environments** 3. **Never commit secrets to version control** 4. **Rotate keys regularly** 5. **Use secure storage in production** (Azure Key Vault, AWS Secrets Manager) 6. **Enable HTTPS only** --- ## Testing Authentication ```csharp using System; using System.Text.Json; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Legnext.SDK.Api; using Legnext.SDK.Client; using Legnext.SDK.Extensions; string apiKey = Environment.GetEnvironmentVariable("LEGNEXT_API_KEY"); var services = new ServiceCollection(); services.AddApi(config => { config.AddApiHttpClients(client => { client.BaseAddress = new Uri("https://api.legnext.ai"); }); }); var provider = services.BuildServiceProvider(); var accountApi = provider.GetRequiredService(); try { var response = await accountApi.ApiAccountBalanceGetAsync( new Option(apiKey) ); if (response.IsOk) { Console.WriteLine("✅ Authentication successful!"); var jsonDoc = JsonDocument.Parse(response.RawContent); if (jsonDoc.RootElement.TryGetProperty("data", out var data)) { if (data.TryGetProperty("balance_usd", out var balance)) { Console.WriteLine($"Balance: ${balance.GetDecimal()} USD"); } } } } catch (Exception e) { Console.WriteLine("❌ Authentication failed"); Console.WriteLine($"Error: {e.Message}"); } ``` --- ## Next Steps - [Image Generation](https://docs.legnext.ai/sdk/csharp/image-generation) - [Video Generation](https://docs.legnext.ai/sdk/csharp/video-generation) - [Task Management](https://docs.legnext.ai/sdk/csharp/task-management) - [Quick Start](https://docs.legnext.ai/sdk/csharp/quickstart) --- # Quick Start _Get started with the Legnext C#/.NET SDK_ ## 1. Install ```bash dotnet add package Legnext.SDK ``` ## 2. Set API Key ```bash export LEGNEXT_API_KEY="your-api-key" ``` ## 3. Basic Example ```csharp using System; using System.Text.Json; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Legnext.SDK.Api; using Legnext.SDK.Client; using Legnext.SDK.Extensions; class Program { static async Task Main(string[] args) { string apiKey = Environment.GetEnvironmentVariable("LEGNEXT_API_KEY"); // Set up dependency injection var services = new ServiceCollection(); services.AddApi(config => { config.AddApiHttpClients(client => { client.BaseAddress = new Uri("https://api.legnext.ai"); }); }); var provider = services.BuildServiceProvider(); var imageApi = provider.GetRequiredService(); try { // Generate image var request = new Dictionary { { "text", "a beautiful sunset over mountains" } }; var response = await imageApi.ApiV1DiffusionPostAsync( new Option(apiKey), request ); if (response.IsOk) { var jsonDoc = JsonDocument.Parse(response.RawContent); if (jsonDoc.RootElement.TryGetProperty("job_id", out var jobId)) { Console.WriteLine($"Job ID: {jobId.GetString()}"); } if (jsonDoc.RootElement.TryGetProperty("status", out var status)) { Console.WriteLine($"Status: {status.GetString()}"); } } } catch (Exception e) { Console.WriteLine($"Error: {e.Message}"); } } } ``` ## 4. Check Task Status ```csharp using System.Text.Json; using Legnext.SDK.Api; var videoApi = provider.GetRequiredService(); try { var response = await videoApi.ApiV1JobJobIdGetAsync( jobId, new Option(apiKey) ); if (response.IsOk) { var jsonDoc = JsonDocument.Parse(response.RawContent); var root = jsonDoc.RootElement; if (root.TryGetProperty("status", out var status)) { Console.WriteLine($"Status: {status.GetString()}"); } if (root.TryGetProperty("task_type", out var taskType)) { Console.WriteLine($"Task Type: {taskType.GetString()}"); } if (root.TryGetProperty("output", out var output) && output.TryGetProperty("image_urls", out var imageUrls)) { Console.WriteLine("Images:"); foreach (var url in imageUrls.EnumerateArray()) { Console.WriteLine($" - {url.GetString()}"); } } } } catch (Exception e) { Console.WriteLine($"Error: {e.Message}"); } ``` ## Error Handling ```csharp try { var response = await imageApi.ApiV1DiffusionPostAsync( new Option(apiKey), request ); if (response.IsOk) { // Parse and handle successful response var jsonDoc = JsonDocument.Parse(response.RawContent); // Process result... } else { Console.WriteLine($"Request failed with status: {response.StatusCode}"); Console.WriteLine($"Response: {response.RawContent}"); } } catch (Exception e) { Console.WriteLine($"Error: {e.Message}"); } ``` ## Available APIs - `IImageApi` - Text to image, variations, upscaling, editing - `IVideoApi` - Video generation, upscaling, and task status - `IAccountManagementApi` - Account balance and information ## Important Notes - The SDK uses dependency injection with `Microsoft.Extensions.DependencyInjection` - Namespace is `Legnext.SDK.*` - API methods use `Option` types for optional parameters - Responses provide `IsOk` property and `RawContent` for result data - Base URL is `https://api.legnext.ai` (no `/api` suffix) --- # Image Generation _Generate and manipulate images using C#/.NET SDK_ ## Setup ```csharp using System; using System.Text.Json; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Legnext.SDK.Api; using Legnext.SDK.Client; using Legnext.SDK.Extensions; string apiKey = Environment.GetEnvironmentVariable("LEGNEXT_API_KEY"); var services = new ServiceCollection(); services.AddApi(config => { config.AddApiHttpClients(client => { client.BaseAddress = new Uri("https://api.legnext.ai"); }); }); var provider = services.BuildServiceProvider(); var imageApi = provider.GetRequiredService(); ``` ## Text-to-Image (Diffusion) Generate images from text descriptions: ```csharp var request = new Dictionary { { "text", "a beautiful sunset over mountains" }, { "callback", "https://example.com/callback" } }; var response = await imageApi.ApiV1DiffusionPostAsync( new Option(apiKey), request ); if (response.IsOk) { var jsonDoc = JsonDocument.Parse(response.RawContent); if (jsonDoc.RootElement.TryGetProperty("job_id", out var jobId)) { Console.WriteLine($"Job ID: {jobId.GetString()}"); } } ``` **With Additional Parameters:** ```csharp var request = new Dictionary { { "text", "a futuristic city at night" }, { "aspect_ratio", "16:9" }, { "version", "6.1" }, { "quality", "high" }, { "callback", "https://example.com/callback" } }; ``` ## Image Upscaling Enhance image resolution: ```csharp var request = new Dictionary { { "job_id", "original-job-id" }, { "imageNo", 0 }, // Index of image to upscale (0-3) { "callback", "https://example.com/callback" } }; var response = await imageApi.ApiV1UpscalePostAsync( new Option(apiKey), request ); if (response.IsOk) { var jsonDoc = JsonDocument.Parse(response.RawContent); if (jsonDoc.RootElement.TryGetProperty("job_id", out var jobId)) { Console.WriteLine($"Upscale Job ID: {jobId.GetString()}"); } } ``` ## Image Variation Create variations of existing images: ```csharp var request = new Dictionary { { "job_id", "original-job-id" }, { "imageNo", 2 }, // Which image to vary (0-3) { "remixPrompt", "same image but with different colors" }, { "callback", "https://example.com/callback" } }; var response = await imageApi.ApiV1VariationPostAsync( new Option(apiKey), request ); if (response.IsOk) { var jsonDoc = JsonDocument.Parse(response.RawContent); if (jsonDoc.RootElement.TryGetProperty("job_id", out var jobId)) { Console.WriteLine($"Variation Job ID: {jobId.GetString()}"); } } ``` ## Image Blending Combine multiple images: ```csharp var request = new Dictionary { { "imgUrls", new List { "https://example.com/image1.jpg", "https://example.com/image2.jpg" } }, { "aspect_ratio", "1:1" }, { "callback", "https://example.com/callback" } }; var response = await imageApi.ApiV1BlendPostAsync( new Option(apiKey), request ); if (response.IsOk) { var jsonDoc = JsonDocument.Parse(response.RawContent); // Process response... } ``` ## Image Editing Edit specific parts of an image: ```csharp var request = new Dictionary { { "canvas", new Dictionary { { "width", 512 }, { "height", 512 } } }, { "imgPos", new Dictionary { { "x", 0 }, { "y", 0 } } }, { "remixPrompt", "add a rainbow in the sky" }, { "callback", "https://example.com/callback" } }; var response = await imageApi.ApiV1EditPostAsync( new Option(apiKey), request ); if (response.IsOk) { var jsonDoc = JsonDocument.Parse(response.RawContent); // Process response... } ``` ## Image Inpainting Inpaint specific regions of an image: ```csharp var request = new Dictionary { { "mask", new Dictionary { { "x", 0 }, { "y", 0 }, { "width", 256 }, { "height", 256 } } }, { "remixPrompt", "a detailed painting" }, { "callback", "https://example.com/callback" } }; var response = await imageApi.ApiV1InpaintPostAsync( new Option(apiKey), request ); if (response.IsOk) { var jsonDoc = JsonDocument.Parse(response.RawContent); if (jsonDoc.RootElement.TryGetProperty("job_id", out var jobId)) { Console.WriteLine($"Inpaint Job ID: {jobId.GetString()}"); } } ``` ## Image Outpainting Extend image boundaries: ```csharp var request = new Dictionary { { "scale", 1.5 }, // Scaling factor (1.1-3.0) { "remixPrompt", "extend the scene naturally" }, { "callback", "https://example.com/callback" } }; var response = await imageApi.ApiV1OutpaintPostAsync( new Option(apiKey), request ); if (response.IsOk) { var jsonDoc = JsonDocument.Parse(response.RawContent); if (jsonDoc.RootElement.TryGetProperty("job_id", out var jobId)) { Console.WriteLine($"Outpaint Job ID: {jobId.GetString()}"); } } ``` ## Image Panning Pan across an image: ```csharp var request = new Dictionary { { "direction", 0 }, // 0=Down, 1=Right, 2=Up, 3=Left { "scale", 1.5 }, // Scaling factor (1.1-3.0) { "remixPrompt", "continue the scene" }, { "callback", "https://example.com/callback" } }; var response = await imageApi.ApiV1PanPostAsync( new Option(apiKey), request ); if (response.IsOk) { var jsonDoc = JsonDocument.Parse(response.RawContent); if (jsonDoc.RootElement.TryGetProperty("job_id", out var jobId)) { Console.WriteLine($"Pan Job ID: {jobId.GetString()}"); } } ``` ## Image Remixing Remix an image with a different style or concept: ```csharp var request = new Dictionary { { "job_id", "original-job-id" }, { "imageNo", 1 }, // Which image to remix (0-3) { "mode", 0 }, // 0=Strong, 1=Subtle { "remixPrompt", "same scene but in oil painting style" }, { "callback", "https://example.com/callback" } }; var response = await imageApi.ApiV1RemixPostAsync( new Option(apiKey), request ); if (response.IsOk) { var jsonDoc = JsonDocument.Parse(response.RawContent); if (jsonDoc.RootElement.TryGetProperty("job_id", out var jobId)) { Console.WriteLine($"Remix Job ID: {jobId.GetString()}"); } } ``` ## Response Handling All responses follow this pattern: ```csharp var response = await imageApi.SomeMethodAsync(...); if (response.IsOk) { // Parse the JSON response var jsonDoc = JsonDocument.Parse(response.RawContent); var root = jsonDoc.RootElement; // Access properties if (root.TryGetProperty("job_id", out var jobId)) { string jobIdValue = jobId.GetString(); } if (root.TryGetProperty("status", out var status)) { string statusValue = status.GetString(); } } else { Console.WriteLine($"Request failed: {response.StatusCode}"); Console.WriteLine($"Response: {response.RawContent}"); } ``` ## Next Steps - [Video Generation](https://docs.legnext.ai/sdk/csharp/video-generation) - [Task Management](https://docs.legnext.ai/sdk/csharp/task-management) - [Authentication](https://docs.legnext.ai/sdk/csharp/authentication) --- # Video Generation _Generate and manipulate videos using C#/.NET SDK_ ## Setup ```csharp using System; using System.Text.Json; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Legnext.SDK.Api; using Legnext.SDK.Client; using Legnext.SDK.Extensions; string apiKey = Environment.GetEnvironmentVariable("LEGNEXT_API_KEY"); var services = new ServiceCollection(); services.AddApi(config => { config.AddApiHttpClients(client => { client.BaseAddress = new Uri("https://api.legnext.ai"); }); }); var provider = services.BuildServiceProvider(); var videoApi = provider.GetRequiredService(); ``` ## Text-to-Video Generate videos from text descriptions: ```csharp var request = new Dictionary { { "text", "a cat walking in a garden" }, { "videoType", 0 }, // 0=480p, 1=720p { "callback", "https://example.com/callback" } }; var response = await videoApi.ApiV1VideoDiffusionPostAsync( new Option(apiKey), request ); if (response.IsOk) { var jsonDoc = JsonDocument.Parse(response.RawContent); if (jsonDoc.RootElement.TryGetProperty("job_id", out var jobId)) { Console.WriteLine($"Job ID: {jobId.GetString()}"); } } ``` **With Additional Parameters:** ```csharp var request = new Dictionary { { "text", "sunset over ocean waves" }, { "aspect_ratio", "16:9" }, { "duration", 5 }, { "videoType", 1 }, // 0=480p, 1=720p { "callback", "https://example.com/callback" } }; ``` **Image-to-Video (Animate Static Image):** ```csharp var request = new Dictionary { { "jobId", "original-image-job-id" }, { "imageNo", 0 }, // Index of image to animate (0-3) { "videoType", 0 }, // 0=480p, 1=720p { "callback", "https://example.com/callback" } }; var response = await videoApi.ApiV1VideoDiffusionPostAsync( new Option(apiKey), request ); if (response.IsOk) { var jsonDoc = JsonDocument.Parse(response.RawContent); if (jsonDoc.RootElement.TryGetProperty("job_id", out var jobId)) { Console.WriteLine($"Job ID: {jobId.GetString()}"); } } ``` ## Video Upscaling Enhance video resolution: ```csharp var request = new Dictionary { { "jobId", "original-video-job-id" }, { "videoNo", 0 }, // Index of video to upscale (0-3) { "callback", "https://example.com/callback" } }; var response = await videoApi.ApiV1VideoUpscalePostAsync( new Option(apiKey), request ); if (response.IsOk) { var jsonDoc = JsonDocument.Parse(response.RawContent); if (jsonDoc.RootElement.TryGetProperty("job_id", out var jobId)) { Console.WriteLine($"Upscale Job ID: {jobId.GetString()}"); } } ``` ## Extend Video Extend video length: ```csharp var request = new Dictionary { { "jobId", "original-video-job-id" }, { "videoNo", 1 }, // Index of video to extend (0-3) { "callback", "https://example.com/callback" } }; var response = await videoApi.ApiV1ExtendVideoPostAsync( new Option(apiKey), request ); if (response.IsOk) { var jsonDoc = JsonDocument.Parse(response.RawContent); if (jsonDoc.RootElement.TryGetProperty("job_id", out var jobId)) { Console.WriteLine($"Extend Job ID: {jobId.GetString()}"); } } ``` ## Check Task Status Monitor video generation progress: ```csharp string jobId = "your-job-id"; var response = await videoApi.ApiV1JobJobIdGetAsync( jobId, new Option(apiKey) ); if (response.IsOk) { var jsonDoc = JsonDocument.Parse(response.RawContent); var root = jsonDoc.RootElement; if (root.TryGetProperty("status", out var status)) { Console.WriteLine($"Status: {status.GetString()}"); } if (root.TryGetProperty("output", out var output)) { if (output.TryGetProperty("video_urls", out var videoUrls)) { Console.WriteLine("Videos:"); foreach (var url in videoUrls.EnumerateArray()) { Console.WriteLine($" - {url.GetString()}"); } } } } ``` ## Response Handling All responses follow this pattern: ```csharp var response = await videoApi.SomeMethodAsync(...); if (response.IsOk) { // Parse the JSON response var jsonDoc = JsonDocument.Parse(response.RawContent); var root = jsonDoc.RootElement; // Access properties if (root.TryGetProperty("job_id", out var jobId)) { string jobIdValue = jobId.GetString(); } if (root.TryGetProperty("status", out var status)) { string statusValue = status.GetString(); } } else { Console.WriteLine($"Request failed: {response.StatusCode}"); Console.WriteLine($"Response: {response.RawContent}"); } ``` ## Next Steps - [Image Generation](https://docs.legnext.ai/sdk/csharp/image-generation) - [Task Management](https://docs.legnext.ai/sdk/csharp/task-management) - [Authentication](https://docs.legnext.ai/sdk/csharp/authentication) --- # Task Management _Handle async tasks and job status in C#/.NET SDK_ ## Understanding Async Operations All image and video generation operations in the Legnext API are asynchronous. When you submit a request, you receive a `job_id` that you use to check the status and retrieve results. ## Setup ```csharp using System; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Legnext.SDK.Api; using Legnext.SDK.Client; using Legnext.SDK.Extensions; string apiKey = Environment.GetEnvironmentVariable("LEGNEXT_API_KEY"); var services = new ServiceCollection(); services.AddApi(config => { config.AddApiHttpClients(client => { client.BaseAddress = new Uri("https://api.legnext.ai"); }); }); var provider = services.BuildServiceProvider(); var videoApi = provider.GetRequiredService(); ``` ## Checking Task Status Check the status of a job: ```csharp string jobId = "your-job-id"; var response = await videoApi.ApiV1JobJobIdGetAsync( jobId, new Option(apiKey) ); if (response.IsOk) { var jsonDoc = JsonDocument.Parse(response.RawContent); var root = jsonDoc.RootElement; if (root.TryGetProperty("status", out var status)) { string statusValue = status.GetString(); Console.WriteLine($"Status: {statusValue}"); // Common statuses: "pending", "processing", "completed", "failed" switch (statusValue) { case "completed": // Extract results if (root.TryGetProperty("output", out var output)) { if (output.TryGetProperty("image_urls", out var imageUrls)) { foreach (var url in imageUrls.EnumerateArray()) { Console.WriteLine($"Image: {url.GetString()}"); } } } break; case "failed": if (root.TryGetProperty("error", out var error)) { Console.WriteLine($"Error: {error.GetString()}"); } break; case "pending": case "processing": Console.WriteLine("Task still in progress..."); break; } } } ``` ## Polling for Completion Poll a task until it completes: ```csharp public async Task WaitForTaskCompletionAsync( string jobId, int maxAttempts = 60, int delaySeconds = 5) { for (int i = 0; i < maxAttempts; i++) { var response = await videoApi.ApiV1JobJobIdGetAsync( jobId, new Option(apiKey) ); if (response.IsOk) { var jsonDoc = JsonDocument.Parse(response.RawContent); var root = jsonDoc.RootElement; if (root.TryGetProperty("status", out var status)) { string statusValue = status.GetString(); if (statusValue == "completed") { Console.WriteLine("Task completed!"); return jsonDoc; } else if (statusValue == "failed") { throw new Exception("Task failed"); } } } Console.WriteLine($"Attempt {i + 1}/{maxAttempts}: Waiting..."); await Task.Delay(TimeSpan.FromSeconds(delaySeconds)); } throw new TimeoutException("Task did not complete in time"); } ``` ## Complete Example Generate an image and wait for completion: ```csharp using System; using System.Collections.Generic; using System.Text.Json; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Legnext.SDK.Api; using Legnext.SDK.Client; using Legnext.SDK.Extensions; class Program { static async Task Main(string[] args) { string apiKey = Environment.GetEnvironmentVariable("LEGNEXT_API_KEY"); var services = new ServiceCollection(); services.AddApi(config => { config.AddApiHttpClients(client => { client.BaseAddress = new Uri("https://api.legnext.ai"); }); }); var provider = services.BuildServiceProvider(); var imageApi = provider.GetRequiredService(); var videoApi = provider.GetRequiredService(); // Step 1: Generate image var request = new Dictionary { { "text", "a beautiful landscape" } }; var generateResponse = await imageApi.ApiV1DiffusionPostAsync( new Option(apiKey), request ); string jobId = null; if (generateResponse.IsOk) { var jsonDoc = JsonDocument.Parse(generateResponse.RawContent); if (jsonDoc.RootElement.TryGetProperty("job_id", out var jobIdProp)) { jobId = jobIdProp.GetString(); Console.WriteLine($"Job created: {jobId}"); } } if (jobId == null) { Console.WriteLine("Failed to create job"); return; } // Step 2: Poll until complete for (int i = 0; i < 60; i++) { await Task.Delay(TimeSpan.FromSeconds(5)); var statusResponse = await videoApi.ApiV1JobJobIdGetAsync( jobId, new Option(apiKey) ); if (statusResponse.IsOk) { var jsonDoc = JsonDocument.Parse(statusResponse.RawContent); var root = jsonDoc.RootElement; if (root.TryGetProperty("status", out var status)) { string statusValue = status.GetString(); Console.WriteLine($"Status: {statusValue}"); if (statusValue == "completed") { // Get image URLs if (root.TryGetProperty("output", out var output) && output.TryGetProperty("image_urls", out var imageUrls)) { Console.WriteLine("Generated images:"); foreach (var url in imageUrls.EnumerateArray()) { Console.WriteLine($" - {url.GetString()}"); } } break; } else if (statusValue == "failed") { Console.WriteLine("Task failed"); break; } } } } } } ``` ## Error Handling Handle errors during task polling: ```csharp try { var response = await videoApi.ApiV1JobJobIdGetAsync( jobId, new Option(apiKey) ); if (response.IsOk) { var jsonDoc = JsonDocument.Parse(response.RawContent); // Process response... } else { Console.WriteLine($"Request failed: {response.StatusCode}"); Console.WriteLine($"Response: {response.RawContent}"); } } catch (Exception e) { Console.WriteLine($"Error: {e.Message}"); } ``` ## Best Practices 1. **Polling Interval**: Use 5-10 second intervals to avoid rate limiting 2. **Timeout**: Set a reasonable maximum wait time (5-10 minutes) 3. **Error Handling**: Always check for "failed" status 4. **Cancellation**: Support `CancellationToken` for long-running operations ## Next Steps - [Image Generation](https://docs.legnext.ai/sdk/csharp/image-generation) - [Video Generation](https://docs.legnext.ai/sdk/csharp/video-generation) - [Authentication](https://docs.legnext.ai/sdk/csharp/authentication) --- # Installation _Install the Legnext Rust SDK_ ## Requirements - **Rust**: Version 1.70 or higher - **Cargo**: Rust package manager ## Add to Cargo.toml Add this dependency to your `Cargo.toml`: ```toml [dependencies] legnext-sdk = "1.0.0" ``` ## Install via Cargo ```bash cargo add legnext-sdk ``` ## Verify Installation ```bash cargo tree | grep legnext ``` ## Build Your Project ```bash cargo build ``` --- # Authentication _Set up authentication for the Legnext Rust SDK_ ## Get Your API Key 1. Visit [Legnext Dashboard](https://dashboard.legnext.ai) 2. Log in to your account 3. Navigate to **API Keys** section 4. Create a new API key 5. Copy and save it securely ## Using Your API Key ### Method 1: Direct Initialization ```rust use legnext_rust_sdk::apis::configuration::Configuration; use legnext_rust_sdk::apis::image_api; #[tokio::main] async fn main() { let mut config = Configuration::new(); config.base_path = "https://api.legnext.ai".to_string(); let api_key = "your-api-key-here"; // Use api_key in function calls } ``` ### Method 2: Environment Variable (Recommended) Set the environment variable: ```bash # macOS/Linux export LEGNEXT_API_KEY="your-api-key-here" # Windows CMD set LEGNEXT_API_KEY=your-api-key-here # Windows PowerShell $env:LEGNEXT_API_KEY="your-api-key-here" ``` Then in your code: ```rust use std::env; use legnext_rust_sdk::apis::configuration::Configuration; #[tokio::main] async fn main() { let mut config = Configuration::new(); config.base_path = "https://api.legnext.ai".to_string(); let api_key = env::var("LEGNEXT_API_KEY") .expect("LEGNEXT_API_KEY environment variable not set"); // Use api_key in function calls } ``` ### Method 3: Using dotenv Crate Add to `Cargo.toml`: ```toml [dependencies] dotenv = "0.15" legnext-rust-sdk = "1.0" tokio = { version = "1", features = ["full"] } ``` Create `.env` file: ```env LEGNEXT_API_KEY=your-api-key-here LEGNEXT_BASE_URL=https://api.legnext.ai ``` In your code: ```rust use dotenv::dotenv; use std::env; use legnext_rust_sdk::apis::configuration::Configuration; #[tokio::main] async fn main() { dotenv().ok(); let mut config = Configuration::new(); config.base_path = env::var("LEGNEXT_BASE_URL") .unwrap_or_else(|_| "https://api.legnext.ai".to_string()); let api_key = env::var("LEGNEXT_API_KEY") .expect("LEGNEXT_API_KEY not found in environment"); // Use api_key in function calls } ``` ## Security Best Practices ⚠️ **Never hardcode API keys in your code** ✅ **Always use environment variables or .env files** ✅ **Add `.env` to `.gitignore`** ✅ **Use `expect()` or proper error handling for missing keys** ✅ **Rotate keys regularly and revoke compromised ones** --- ## Next Steps - [Quick Start](https://docs.legnext.ai/sdk/rust/quickstart) - [Image Generation API](https://docs.legnext.ai/sdk/rust/image-generation) - [Video Generation API](https://docs.legnext.ai/sdk/rust/video-generation) --- # Quick Start _Get started with the Legnext Rust SDK_ ## 1. Add Dependency Add to your `Cargo.toml`: ```toml [dependencies] legnext-rust-sdk = "1.0.0" tokio = { version = "1", features = ["full"] } ``` ## 2. Set API Key ```bash export LEGNEXT_API_KEY="your-api-key" ``` ## 3. Basic Example ```rust use legnext_rust_sdk::apis::configuration::Configuration; use legnext_rust_sdk::apis::image_api; use std::env; #[tokio::main] async fn main() -> Result<(), Box> { // Configure API client let mut config = Configuration::new(); config.base_path = "https://api.legnext.ai".to_string(); let api_key = env::var("LEGNEXT_API_KEY")?; // Generate image let mut request = std::collections::HashMap::new(); request.insert("text".to_string(), serde_json::json!("a beautiful sunset over mountains")); match image_api::api_v1_diffusion_post(&config, Some(&api_key), Some(request)).await { Ok(response) => { println!("Response: {:?}", response); } Err(e) => { eprintln!("Error: {:?}", e); } } Ok(()) } ``` ## 4. Check Task Status ```rust use legnext_rust_sdk::apis::video_api; let job_id = "your-job-id-here"; match video_api::api_v1_job_job_id_get(&config, &job_id, Some(&api_key)).await { Ok(task_response) => { if let Some(status) = task_response.status { println!("Status: {}", status); } if let Some(output) = task_response.output { if let Some(image_urls) = output.image_urls { println!("Images: {:?}", image_urls); } } } Err(e) => { eprintln!("Error: {:?}", e); } } ``` ## Error Handling ```rust match image_api::api_v1_diffusion_post(&config, Some(&api_key), Some(request)).await { Ok(response) => { // Handle success println!("Success: {:?}", response); } Err(e) => { eprintln!("Error: {:?}", e); } } ``` ## Async/Await All API calls are async and require an async runtime like Tokio: ```toml [dependencies] tokio = { version = "1", features = ["full"] } ``` ## Available APIs - `image_api` - Text to image, variations, upscaling, editing - `video_api` - Video generation, upscaling, and task status - `account_management_api` - Account balance and information --- # Image Generation _Image generation API reference for Rust SDK_ ## api_v1_diffusion_post() Create a new text-to-image generation task. ```rust use legnext_rust_sdk::{ apis::configuration::Configuration, apis::image_api, }; use std::collections::HashMap; #[tokio::main] async fn main() -> Result<(), Box> { let mut config = Configuration::new(); config.base_path = "https://api.legnext.ai".to_string(); let api_key = "your-api-key-here"; let mut body = HashMap::new(); body.insert("text".to_string(), "a serene mountain landscape at sunset"); body.insert("callback".to_string(), "https://your-domain.com/webhook"); let response = image_api::api_v1_diffusion_post( &config, Some(api_key), Some(serde_json::to_value(body)?), ).await?; println!("Job ID: {:?}", response.job_id); Ok(()) } ``` **Parameters:** - `configuration` (&Configuration): API configuration - `x_api_key` (Option<&str>): Your API key - `body` (Option): Request body with: - `text` (String): Text prompt (1-8192 characters) - `callback` (String, optional): Webhook URL **Returns:** `Result` with `job_id` and `status` --- ## api_v1_vary_post() Create variations of a generated image. ```rust let mut body = HashMap::new(); body.insert("jobId", "original-job-id"); body.insert("imageNo", 0); body.insert("type", 1); // 0=Subtle, 1=Strong body.insert("remixPrompt", "add more clouds"); body.insert("callback", "https://your-domain.com/webhook"); let response = image_api::api_v1_vary_post( &config, Some(api_key), Some(serde_json::to_value(body)?), ).await?; ``` --- ## api_v1_upscale_post() Upscale a generated image. ```rust let mut body = HashMap::new(); body.insert("jobId", "original-job-id"); body.insert("imageNo", 0); body.insert("type", 1); // 0=Subtle, 1=Creative body.insert("callback", "https://your-domain.com/webhook"); let response = image_api::api_v1_upscale_post( &config, Some(api_key), Some(serde_json::to_value(body)?), ).await?; ``` --- ## api_v1_reroll_post() Regenerate with the same prompt. ```rust let mut body = HashMap::new(); body.insert("jobId", "original-job-id"); body.insert("callback", "https://your-domain.com/webhook"); image_api::api_v1_reroll_post( &config, Some(api_key), Some(serde_json::to_value(body)?), ).await?; ``` --- ## api_v1_blend_post() Blend 2-5 images together. ```rust let mut body = HashMap::new(); body.insert("imgUrls", vec![ "https://example.com/image1.png", "https://example.com/image2.png" ]); body.insert("aspect_ratio", "1:1"); body.insert("callback", "https://your-domain.com/webhook"); image_api::api_v1_blend_post( &config, Some(api_key), Some(serde_json::to_value(body)?), ).await?; ``` --- ## api_v1_describe_post() Generate text descriptions from an image. ```rust let mut body = HashMap::new(); body.insert("imgUrl", "https://example.com/image.png"); body.insert("callback", "https://your-domain.com/webhook"); image_api::api_v1_describe_post( &config, Some(api_key), Some(serde_json::to_value(body)?), ).await?; ``` --- ## api_v1_edit_post() Edit an image with text description. ```rust let mut body = HashMap::new(); body.insert("jobId", "original-job-id"); body.insert("imageNo", 0); body.insert("canvas", 512); // Required: canvas size body.insert("imgPos", "center"); // Required: image position body.insert("remixPrompt", "change the sky to sunset colors"); body.insert("callback", "https://your-domain.com/webhook"); image_api::api_v1_edit_post( &config, Some(api_key), Some(serde_json::to_value(body)?), ).await?; ``` --- ## api_v1_inpaint_post() Fill masked regions in an image. ```rust let mut body = HashMap::new(); body.insert("jobId", "original-job-id"); body.insert("imageNo", 0); body.insert("remixPrompt", "fill with forest landscape"); body.insert("mask", serde_json::json!({ "type": "url", "url": "https://example.com/mask.png" })); body.insert("callback", "https://your-domain.com/webhook"); image_api::api_v1_inpaint_post( &config, Some(api_key), Some(serde_json::to_value(body)?), ).await?; ``` --- ## api_v1_outpaint_post() Extend image boundaries. ```rust let mut body = HashMap::new(); body.insert("jobId", "original-job-id"); body.insert("imageNo", 0); body.insert("scale", 1.5); body.insert("remixPrompt", "extend with matching landscape"); body.insert("callback", "https://your-domain.com/webhook"); image_api::api_v1_outpaint_post( &config, Some(api_key), Some(serde_json::to_value(body)?), ).await?; ``` --- ## api_v1_pan_post() Create panoramic or panned views. ```rust let mut body = HashMap::new(); body.insert("jobId", "original-job-id"); body.insert("imageNo", 0); body.insert("direction", 3); // 0=Down, 1=Right, 2=Up, 3=Left body.insert("scale", 1.5); // Range: 1.1-3.0 body.insert("remixPrompt", "add more elements in the direction"); body.insert("callback", "https://your-domain.com/webhook"); image_api::api_v1_pan_post( &config, Some(api_key), Some(serde_json::to_value(body)?), ).await?; ``` --- ## api_v1_remix_post() Create a remix of an image with different settings. ```rust let mut body = HashMap::new(); body.insert("jobId", "original-job-id"); body.insert("imageNo", 0); body.insert("mode", 0); // 0=Strong, 1=Subtle body.insert("remixPrompt", "dramatic lighting and vibrant colors"); body.insert("callback", "https://your-domain.com/webhook"); let response = image_api::api_v1_remix_post( &config, Some(api_key), Some(serde_json::to_value(body)?), ).await?; println!("Remix Job ID: {:?}", response.job_id); ``` --- ## api_v1_shorten_post() Optimize and simplify prompts. ```rust let mut body = HashMap::new(); body.insert("prompt", "your very long and detailed prompt here..."); body.insert("callback", "https://your-domain.com/webhook"); let response = image_api::api_v1_shorten_post( &config, Some(api_key), Some(serde_json::to_value(body)?), ).await?; println!("Optimized prompt: {:?}", response.shortened_prompt); ``` --- ## Next Steps - [Video Generation](https://docs.legnext.ai/sdk/rust/video-generation) - [Task Management](https://docs.legnext.ai/sdk/rust/task-management) - [Quick Start](https://docs.legnext.ai/sdk/rust/quickstart) --- # Video Generation _Video generation API reference for Rust SDK_ ## api_v1_video_diffusion_post() Generate a video from text prompt, with optional image URL or image animation. ```rust use legnext_rust_sdk::{ apis::configuration::Configuration, apis::video_api, }; use std::collections::HashMap; #[tokio::main] async fn main() -> Result<(), Box> { let mut config = Configuration::new(); config.base_path = "https://api.legnext.ai".to_string(); let api_key = "your-api-key-here"; // Generate from text only let mut body = HashMap::new(); body.insert("prompt", "a flowing river through mountains"); body.insert("videoType", 1); // 0=480p, 1=720p body.insert("callback", "https://your-domain.com/webhook"); let response = video_api::api_v1_video_diffusion_post( &config, Some(api_key), Some(serde_json::to_value(body)?), ).await?; println!("Job ID: {:?}", response.job_id); Ok(()) } ``` **Generate from Image URL:** ```rust // Generate from image URL let mut body = HashMap::new(); body.insert( "prompt", "https://example.com/image.png a flowing river through mountains" ); body.insert("videoType", 1); // 0=480p, 1=720p body.insert("callback", "https://your-domain.com/webhook"); let response = video_api::api_v1_video_diffusion_post( &config, Some(api_key), Some(serde_json::to_value(body)?), ).await?; ``` **Animate Image from Previous Job:** ```rust // Animate image from previous generation job let mut body = HashMap::new(); body.insert("prompt", "a flowing river through mountains"); body.insert("jobId", "original-image-job-id"); body.insert("imageNo", 0); // Image index from job body.insert("videoType", 1); // 0=480p, 1=720p body.insert("callback", "https://your-domain.com/webhook"); let response = video_api::api_v1_video_diffusion_post( &config, Some(api_key), Some(serde_json::to_value(body)?), ).await?; ``` **Parameters:** - `configuration` (&Configuration): API configuration - `x_api_key` (Option<&str>): Your API key - `body` (Option): Request body with: - `prompt` (String): Video prompt or "[image_url] prompt text" (1-8192 characters) - `jobId` (String, optional): Original image job ID for animation mode - `imageNo` (Integer, optional): Image index when using jobId (0-3) - `videoType` (Integer, optional): Quality (0=480p, 1=720p) - `callback` (String, optional): Webhook URL **Returns:** `Result` with `job_id` and `status` --- ## api_v1_extend_video_post() Extend an existing video. ```rust let mut body = HashMap::new(); body.insert("jobId", "original-video-job-id"); body.insert("videoNo", 0); body.insert("prompt", "continue with dramatic lighting"); body.insert("callback", "https://your-domain.com/webhook"); let response = video_api::api_v1_extend_video_post( &config, Some(api_key), Some(serde_json::to_value(body)?), ).await?; println!("Extension Job ID: {:?}", response.job_id); ``` **Parameters:** - `configuration` (&Configuration): API configuration - `x_api_key` (Option<&str>): Your API key - `body` (Option): Request body with: - `jobId` (String): Original video task ID - `videoNo` (Integer): Video index (0-3) - `prompt` (String, optional): Extension prompt (1-8192 characters) - `callback` (String, optional): Webhook URL **Returns:** `Result` with `job_id` and `status` --- ## api_v1_video_upscale_post() Upscale video to higher resolution. ```rust let mut body = HashMap::new(); body.insert("jobId", "original-video-job-id"); body.insert("videoNo", 0); body.insert("callback", "https://your-domain.com/webhook"); let response = video_api::api_v1_video_upscale_post( &config, Some(api_key), Some(serde_json::to_value(body)?), ).await?; println!("Upscale Job ID: {:?}", response.job_id); ``` **Parameters:** - `configuration` (&Configuration): API configuration - `x_api_key` (Option<&str>): Your API key - `body` (Option): Request body with: - `jobId` (String): Original video task ID - `videoNo` (Integer): Video index (0-3) - `callback` (String, optional): Webhook URL **Returns:** `Result` with `job_id` and `status` --- ## Complete Example ```rust use legnext_rust_sdk::{ apis::configuration::Configuration, apis::video_api, }; use std::collections::HashMap; #[tokio::main] async fn main() -> Result<(), Box> { let mut config = Configuration::new(); config.base_path = "https://api.legnext.ai".to_string(); let api_key = std::env::var("LEGNEXT_API_KEY") .expect("LEGNEXT_API_KEY environment variable not set"); // Step 1: Generate video let mut body = HashMap::new(); body.insert("prompt", "a beautiful sunset over the ocean"); body.insert("videoType", 1); let response = video_api::api_v1_video_diffusion_post( &config, Some(&api_key), Some(serde_json::to_value(body)?), ).await?; let job_id = response.job_id.unwrap(); println!("Video generation started: {}", job_id); // Step 2: Wait for completion (see Task Management docs) // ... // Step 3: Extend the video let mut extend_body = HashMap::new(); extend_body.insert("jobId", &job_id); extend_body.insert("videoNo", 0); extend_body.insert("prompt", "continue with dramatic clouds"); let extend_response = video_api::api_v1_extend_video_post( &config, Some(&api_key), Some(serde_json::to_value(extend_body)?), ).await?; println!("Video extension started: {:?}", extend_response.job_id); Ok(()) } ``` --- ## Next Steps - [Image Generation](https://docs.legnext.ai/sdk/rust/image-generation) - [Task Management](https://docs.legnext.ai/sdk/rust/task-management) - [Quick Start](https://docs.legnext.ai/sdk/rust/quickstart) --- # Task Management _Task status, polling, and error handling for Rust SDK_ ## api_v1_job_job_id_get() Get current task status: ```rust use legnext_rust_sdk::{ apis::configuration::Configuration, apis::image_api, }; #[tokio::main] async fn main() -> Result<(), Box> { let mut config = Configuration::new(); config.base_path = "https://api.legnext.ai".to_string(); let api_key = "your-api-key-here"; let job_id = "job-123"; let task = image_api::api_v1_job_job_id_get( &config, job_id, Some(api_key), ).await?; println!("Status: {:?}", task.status); println!("Progress: {}%", task.progress.unwrap_or(0)); if task.status == Some("completed".to_string()) { println!("Result: {:?}", task.output); } Ok(()) } ``` --- ## Polling for Completion Wait for task completion with polling: ```rust use legnext_rust_sdk::{ apis::configuration::Configuration, apis::image_api, }; use std::time::Duration; use tokio::time::sleep; async fn wait_for_completion( config: &Configuration, job_id: &str, api_key: &str, timeout_seconds: u64, poll_interval_seconds: u64, ) -> Result> { let start_time = std::time::Instant::now(); let timeout = Duration::from_secs(timeout_seconds); loop { let task = image_api::api_v1_job_job_id_get( config, job_id, Some(api_key), ).await?; println!("Current status: {:?}", task.status); if task.status == Some("completed".to_string()) { println!("Task completed successfully!"); println!("Output: {:?}", task.output); return Ok(task.output.unwrap_or_default()); } else if task.status == Some("failed".to_string()) { return Err(format!("Task failed: {:?}", task.error).into()); } // Check timeout if start_time.elapsed() > timeout { return Err(format!("Task timeout after {} seconds", timeout_seconds).into()); } // Wait before next poll sleep(Duration::from_secs(poll_interval_seconds)).await; } } ``` **Usage:** ```rust #[tokio::main] async fn main() -> Result<(), Box> { let mut config = Configuration::new(); config.base_path = "https://api.legnext.ai".to_string(); let api_key = std::env::var("LEGNEXT_API_KEY")?; let job_id = "job-123"; match wait_for_completion(&config, job_id, &api_key, 300, 3).await { Ok(result) => println!("Final result: {:?}", result), Err(e) => eprintln!("Error: {}", e), } Ok(()) } ``` --- ## Complete Example with Error Handling ```rust use legnext_rust_sdk::{ apis::configuration::Configuration, apis::image_api, }; use std::collections::HashMap; use std::time::Duration; use tokio::time::sleep; async fn wait_for_completion( config: &Configuration, job_id: &str, api_key: &str, timeout_seconds: u64, poll_interval_seconds: u64, ) -> Result> { let start_time = std::time::Instant::now(); let timeout = Duration::from_secs(timeout_seconds); loop { let task = image_api::api_v1_job_job_id_get( config, job_id, Some(api_key), ).await?; if task.status == Some("completed".to_string()) { return Ok(task.output.unwrap_or_default()); } else if task.status == Some("failed".to_string()) { return Err(format!("Task failed: {:?}", task.error).into()); } if start_time.elapsed() > timeout { return Err(format!("Task timeout after {} seconds", timeout_seconds).into()); } sleep(Duration::from_secs(poll_interval_seconds)).await; } } #[tokio::main] async fn main() -> Result<(), Box> { let mut config = Configuration::new(); config.base_path = "https://api.legnext.ai".to_string(); let api_key = std::env::var("LEGNEXT_API_KEY") .expect("LEGNEXT_API_KEY environment variable not set"); // Step 1: Start generation let mut body = HashMap::new(); body.insert("text".to_string(), "a beautiful sunset over mountains"); let response = image_api::api_v1_diffusion_post( &config, Some(&api_key), Some(serde_json::to_value(body)?), ).await?; let job_id = response.job_id.ok_or("No job_id in response")?; println!("Job started: {}", job_id); // Step 2: Poll for completion let result = wait_for_completion(&config, &job_id, &api_key, 600, 3).await?; // Step 3: Get final result println!("Image URLs: {:?}", result); Ok(()) } ``` --- ## Error Handling **HTTP Error Handling:** The Rust SDK returns `Result` types. Handle errors using pattern matching: ```rust use legnext_rust_sdk::apis::Error; match image_api::api_v1_diffusion_post(&config, Some(&api_key), Some(body)).await { Ok(response) => { println!("Success: {:?}", response); } Err(Error::ResponseError(ref content)) => { match content.status { 400 => eprintln!("Validation error: {:?}", content.content), 401 => eprintln!("Authentication error: Invalid API key"), 404 => eprintln!("Resource not found"), 429 => eprintln!("Rate limit exceeded. Please retry later."), 500 | 502 | 503 => eprintln!("Server error: {:?}", content.content), _ => eprintln!("API error ({}): {:?}", content.status, content.content), } } Err(e) => eprintln!("Unexpected error: {:?}", e), } ``` **Common HTTP Status Codes:** | Status Code | Description | Action | |-------------|-------------|--------| | 400 | Invalid request parameters | Check request body format | | 401 | Invalid API key | Verify API key is correct | | 404 | Resource not found | Check job ID exists | | 429 | Rate limit exceeded | Wait and retry with backoff | | 500/502/503 | Server error | Retry with exponential backoff | **Retry Logic with Exponential Backoff:** ```rust use std::time::Duration; use tokio::time::sleep; async fn call_with_retry( api_call: F, max_retries: u32, ) -> Result> where F: Fn() -> futures::future::BoxFuture<'static, Result>, { for i in 0..max_retries { match api_call().await { Ok(result) => return Ok(result), Err(Error::ResponseError(ref content)) => { if content.status == 429 { // Rate limited - wait and retry sleep(Duration::from_secs(5)).await; continue; } else if content.status >= 500 { // Server error - exponential backoff let delay = Duration::from_secs(2_u64.pow(i)); sleep(delay).await; if i == max_retries - 1 { return Err(Box::new(content.clone())); } continue; } else { // Other errors - don't retry return Err(Box::new(content.clone())); } } Err(e) => return Err(Box::new(e)), } } Err("Max retries exceeded".into()) } // Usage let result = call_with_retry( || Box::pin(image_api::api_v1_diffusion_post(&config, Some(&api_key), Some(body.clone()))), 3, ).await?; ``` --- ## Concurrent Operations with Tokio For processing multiple tasks concurrently: ```rust use tokio::try_join; #[tokio::main] async fn main() -> Result<(), Box> { let mut config = Configuration::new(); config.base_path = "https://api.legnext.ai".to_string(); let api_key = std::env::var("LEGNEXT_API_KEY")?; let prompts = vec!["sunset", "mountains", "ocean"]; // Start all generations concurrently let mut handles = vec![]; for prompt in prompts { let config_clone = config.clone(); let api_key_clone = api_key.clone(); let prompt_clone = prompt.to_string(); let handle = tokio::spawn(async move { let mut body = HashMap::new(); body.insert("text".to_string(), prompt_clone.clone()); let response = image_api::api_v1_diffusion_post( &config_clone, Some(&api_key_clone), Some(serde_json::to_value(body)?), ).await?; let job_id = response.job_id.ok_or("No job_id")?; // Wait for completion let result = wait_for_completion( &config_clone, &job_id, &api_key_clone, 600, 3, ).await?; Ok::<_, Box>(result) }); handles.push(handle); } // Wait for all tasks to complete for handle in handles { match handle.await { Ok(Ok(result)) => println!("Image generated: {:?}", result), Ok(Err(e)) => eprintln!("Task error: {}", e), Err(e) => eprintln!("Join error: {}", e), } } Ok(()) } ``` --- ## Progress Callbacks ```rust use std::sync::Arc; use tokio::sync::Mutex; async fn wait_for_completion_with_progress( config: &Configuration, job_id: &str, api_key: &str, on_progress: F, timeout_seconds: u64, poll_interval_seconds: u64, ) -> Result> where F: Fn(i32, &str), { let start_time = std::time::Instant::now(); let timeout = Duration::from_secs(timeout_seconds); loop { let task = image_api::api_v1_job_job_id_get( config, job_id, Some(api_key), ).await?; // Call progress callback on_progress( task.progress.unwrap_or(0), task.status.as_deref().unwrap_or("unknown"), ); if task.status == Some("completed".to_string()) { return Ok(task.output.unwrap_or_default()); } else if task.status == Some("failed".to_string()) { return Err(format!("Task failed: {:?}", task.error).into()); } if start_time.elapsed() > timeout { return Err(format!("Task timeout after {} seconds", timeout_seconds).into()); } sleep(Duration::from_secs(poll_interval_seconds)).await; } } // Usage let result = wait_for_completion_with_progress( &config, &job_id, &api_key, |progress, status| { println!("Progress: {}% - Status: {}", progress, status); }, 600, 3, ).await?; ``` --- ## Learn More - [Image Generation API](https://docs.legnext.ai/sdk/rust/image-generation) - [Video Generation API](https://docs.legnext.ai/sdk/rust/video-generation) - [Quick Start](https://docs.legnext.ai/sdk/rust/quickstart) --- # Integrations Overview _Connect Legnext AI API with your favorite automation platforms_ Integrate Legnext AI API with popular automation and workflow platforms to create powerful image and video generation workflows without writing code. ## Available Integrations - **n8n**: } href="/integrations/n8n"> Connect Legnext with n8n to build automated workflows for image and video generation. Perfect for creating custom automation pipelines. - **Postman**: } href="/integrations/postman"> Test and explore Legnext AI API using our official Postman collection. Perfect for API testing and development. - **Make**: } href="/integrations/make"> Build visual automation workflows with Make (formerly Integromat). Connect with 1000+ apps without coding. - **n8n** - **Postman** - **Make** ### Coming Soon We're working on official integrations for: - **Zapier** - Connect with 5000+ apps Stay tuned for updates! --- ## Benefits of Platform Integrations - **No Code Required** - Build powerful workflows with visual editors - **Connect Multiple Services** - Combine Legnext with other tools in your stack - **Automate Workflows** - Trigger image generation from various events - **Scale Easily** - Handle bulk operations without custom code --- ## Request an Integration Don't see the integration you need? We're always looking to expand our ecosystem. [Request an integration](mailto:support@legnext.ai?subject=Integration%20Request) and let us know what platform you'd like to see next. ## Need Help? If you need assistance with integrations, reach out to our support team at support@legnext.ai --- # n8n Integration _Connect Legnext AI API with n8n to build automated workflows_ ## Overview n8n is a powerful workflow automation tool that allows you to connect various services and APIs. By integrating Legnext AI API with n8n, you can: - **Automate Image Generation** - Trigger image creation based on events from other services - **Build Complex Workflows** - Chain multiple operations together - **Process Data at Scale** - Handle bulk image generation tasks - **No Coding Required** - Use visual workflow editor ## Key Features - **Visual Workflow Builder**: Create complex automations with a drag-and-drop interface. - **Advanced Logic**: Use if-statements, loops, and merges to build sophisticated pipelines. - **Self-Hosted Option**: Run n8n on your own infrastructure for complete data control. - **Community Nodes**: Access a wide range of community-built nodes and workflows. ## Video Tutorial Watch this tutorial to learn how to set up Legnext with n8n: ## Getting Started ### Prerequisites - An n8n instance (self-hosted or cloud) - A Legnext API key ([Get one here](https://legnext.ai)) - Basic understanding of workflow automation ### Installation 1. **Download the Preset Workflow** [Download Preset Workflow](https://raw.githubusercontent.com/leggiemint/legnext-resources/refs/heads/main/example_workflow.json) 2. **Import into n8n** - Open your n8n instance - Go to Workflows - Click "Import from File" - Select the downloaded JSON file 3. **Configure API Credentials** - Add your Legnext API key to the HTTP Request nodes - Test the connection ## Use Cases ### Automated Social Media Content Create a workflow that generates images based on trending topics and posts them to social media platforms. ### E-commerce Product Images Generate product images automatically when new items are added to your inventory system. ### Content Pipeline Build a content creation pipeline that generates images for blog posts, newsletters, or marketing materials. ### Scheduled Image Generation Set up scheduled workflows to generate images at specific times or intervals. ## Best Practices - **Error Handling** - Add error handling nodes to manage API failures gracefully - **Rate Limiting** - Be mindful of API rate limits when processing large batches - **Webhook Configuration** - Use webhooks for async operations to avoid timeout issues - **Data Validation** - Validate input data before sending to the API ## Troubleshooting ### Common Issues **Connection Timeout** - Use webhook callbacks for long-running operations - Increase timeout settings in n8n HTTP Request node **API Key Errors** - Verify your API key is correctly configured - Check that the key has proper permissions **Invalid Parameters** - Review the API documentation for correct parameter formats - Validate your input data before sending requests ## Need Help? If you need assistance with n8n integration, reach out to our support team at support@legnext.ai --- # Postman Collection _Test and explore Legnext AI API using our official Postman collection_ ## Quick Start Get started with our pre-configured Postman collection. Click the button below to fork the collection to your workspace: [Run in Postman](https://www.postman.com/legnext-ai/workspace/legnext-ai-s-workspace/collection/49973316-23452527-b0dc-420a-b21c-cba1d8d5d87a?action=share&source=copy-link&creator=49973316) ## What's Included Our Postman collection includes ready-to-use requests for: ### Image Generation - **Text-to-Image** - Generate images from text descriptions - **Image-to-Image** - Transform existing images - **Upscale** - Enhance image resolution - **Variation** - Create variations of existing images ### Video Generation - **Video Diffusion** - Generate videos from images or text - **Video Extend** - Extend video duration - **Video Upscale** - Enhance video quality ### Task Management - **Get Task Status** - Check task progress - **Get Task Result** - Retrieve completed results - **Cancel Task** - Cancel running tasks ### Account Management - **Get Balance** - Check your account balance and usage ## Prerequisites - A Postman account (free or paid) - Postman Desktop App or Web Client - A Legnext API key ([Get one here](https://legnext.ai)) ## Setup Instructions ### 1. Fork the Collection Click the "Run in Postman" button above to fork the collection to your workspace. ### 2. Configure API Key After importing the collection: 1. Open the collection in Postman 2. Go to the "Variables" tab 3. Set the `api_key` variable to your Legnext API key 4. Save the changes ### 3. Start Testing Select any request from the collection and click "Send" to test the API. ## Collection Features ### Environment Variables The collection uses variables for easy configuration: - `base_url` - API base URL (pre-configured) - `api_key` - Your API key (you need to set this) - `job_id` - Automatically saved from responses for chaining requests ### Pre-Request Scripts Some requests include pre-request scripts to: - Validate required variables - Generate dynamic data - Set up request dependencies ### Test Scripts Responses include test scripts that: - Validate response status - Extract and save job IDs - Check response structure ## Use Cases ### API Exploration Quickly explore all available endpoints and understand request/response formats without writing code. ### Development Testing Test API integration during development with easy-to-modify requests and instant feedback. ### Documentation Reference Use the collection as a living documentation reference with real examples for all endpoints. ### Team Collaboration Share the collection with your team to ensure everyone uses consistent API patterns. ## Tips and Best Practices ### Save Your Responses Use Postman's "Save Response" feature to create examples for your team. ### Use Environments Create different environments (development, staging, production) with different API keys. ### Organize with Folders The collection is organized by feature - use this structure to quickly find what you need. ### Chain Requests Use the saved `job_id` variable to chain related requests together (e.g., generate → upscale → get result). ## Troubleshooting ### "Invalid API Key" Error Make sure you've set your API key in the collection variables: 1. Click on the collection name 2. Go to "Variables" tab 3. Set the `api_key` value 4. Save ### "Request Timeout" Error Some operations (like video generation) take time. Use the task status endpoint to poll for results instead of waiting for the initial request. ### Variables Not Saving Make sure you're saving the collection after making changes to variables. ## Public Workspace Visit our public Postman workspace to explore more: [View Legnext AI Workspace](https://www.postman.com/legnext-ai/workspace/legnext-ai-s-workspace/collection/49973316-23452527-b0dc-420a-b21c-cba1d8d5d87a?action=share&source=copy-link&creator=49973316) ## Need Help? If you need assistance with the Postman collection, reach out to our support team at support@legnext.ai --- # Make Integration _Connect Legnext AI API with Make (formerly Integromat) to build visual automation workflows_ ## Overview Make is a visual platform that lets you design, build, and automate workflows by connecting apps and services. By integrating Legnext AI API with Make, you can: - **Visual Workflow Builder** - Create complex automations with drag-and-drop interface - **Connect 1000+ Apps** - Integrate with popular tools like Google Drive, Slack, Airtable, and more - **Advanced Logic** - Use routers, filters, and conditional logic in your workflows - **Real-time Processing** - Process images and videos as events happen - **No Coding Required** - Build powerful automations without technical expertise ## Getting Started ### Join Our Make Organization Get access to pre-built Legnext templates and modules: [Join Make Organization](https://www.make.com/en/hq/app-invitation/1ff92bec923a3c4561e85cf2da047c12) ### Prerequisites - A Make account (free or paid) - A Legnext API key ([Get one here](https://legnext.ai)) - Basic understanding of workflow automation ### Setup Steps 1. **Join the Organization** - Click the button above to accept the invitation - Log in to your Make account or create a new one 2. **Access Legnext Templates** - Browse pre-built scenarios in the organization - Clone templates to your workspace 3. **Configure API Connection** - Add your Legnext API key to HTTP modules - Test the connection 4. **Customize Your Workflow** - Modify the scenario to fit your needs - Add additional apps and logic ## Use Cases ### Automated Content Creation Create a workflow that monitors your content calendar and automatically generates images when new content is scheduled. **Example Flow:** ``` Google Sheets (New Row) → Legnext (Generate Image) → Google Drive (Save File) → Slack (Send Notification) ``` ### Social Media Automation Generate and post images to multiple social media platforms based on triggers. **Example Flow:** ``` RSS Feed → Legnext (Generate Image) → Dropbox (Save) → Twitter/Instagram (Post) ``` ### E-commerce Product Images Automatically generate product images when new items are added to your store. **Example Flow:** ``` Shopify (New Product) → Legnext (Generate Image) → Shopify (Update Product Image) ``` ### Email Marketing Campaigns Create personalized images for email campaigns based on customer data. **Example Flow:** ``` Mailchimp (New Campaign) → Airtable (Get Data) → Legnext (Generate Images) → Mailchimp (Add Images) ``` ### Video Content Pipeline Build automated video generation workflows for marketing or social media. **Example Flow:** ``` Trello (Card Moved) → Legnext (Generate Video) → Vimeo (Upload) → Email (Send Review Link) ``` ## Key Features ### HTTP Modules Use Make's HTTP modules to interact with the Legnext API: - **HTTP Request** - Make API calls to Legnext endpoints - **Webhooks** - Receive completion notifications from Legnext - **JSON Parsing** - Process API responses ### Data Mapping Map data between apps using Make's intuitive interface: - Transform text data into image prompts - Extract job IDs from responses - Format URLs and parameters ### Error Handling Build robust workflows with Make's error handling: - **Error Handler Routes** - Define fallback actions - **Retry Logic** - Automatically retry failed requests - **Notifications** - Get alerted when errors occur ### Scheduling Run workflows on schedules: - **Interval Scheduling** - Run every N minutes/hours - **Specific Times** - Run at exact times daily/weekly - **Custom Cron** - Advanced scheduling options ## Available Legnext Operations ### Image Generation - Text-to-Image - Image-to-Image - Image Upscaling - Image Variations ### Video Generation - Video Diffusion - Video Extension - Video Upscaling ### Task Management - Get Task Status - Get Task Result - Cancel Task ### Account - Get Balance ## Best Practices ### Use Webhooks for Long Operations For video generation and other long-running tasks: 1. Send the initial API request with a webhook URL 2. Use Make's webhook to receive the completion notification 3. Process the result in a separate scenario ### Handle Rate Limits - Add delay modules between bulk operations - Use Make's scheduling to spread out requests - Monitor your API usage in the Legnext dashboard ### Store Job IDs - Use data stores to track job IDs - Link generation and result retrieval operations - Maintain history of completed tasks ### Test Thoroughly - Use Make's test execution feature - Verify all API connections before going live - Set up error notifications ## Example Scenarios ### Basic Image Generation **Trigger:** Google Form submission **Actions:** 1. Parse form response 2. Call Legnext text-to-image API 3. Wait for completion (webhook or polling) 4. Save image to Google Drive 5. Send email with image link ### Batch Image Processing **Trigger:** New file in Dropbox folder **Actions:** 1. Get file URL from Dropbox 2. Call Legnext image-to-image API 3. Apply style transformation 4. Save result to different folder 5. Update Airtable with status ### Video Generation Pipeline **Trigger:** Scheduled (daily at 9 AM) **Actions:** 1. Get content from CMS (e.g., WordPress) 2. Generate video using Legnext 3. Monitor task status 4. Upload to YouTube when ready 5. Post announcement on social media ## Troubleshooting ### Connection Issues **Problem:** Can't connect to Legnext API **Solution:** - Verify your API key is correct - Check that you're using the correct endpoint URL - Ensure your Make plan supports HTTP requests ### Timeout Errors **Problem:** Scenario times out waiting for response **Solution:** - Use webhook callbacks instead of waiting - Split generation and retrieval into separate scenarios - Use Make's resume feature for long-running operations ### Data Mapping Errors **Problem:** Data not mapping correctly between modules **Solution:** - Use Make's mapping panel to visualize data structure - Test with sample data first - Check JSON response format in API documentation ### Webhook Not Triggering **Problem:** Not receiving webhook notifications **Solution:** - Verify webhook URL is correct in API request - Check Make webhook is active and listening - Test webhook with Make's "Determine data structure" feature ## Resources - [Make Documentation](https://www.make.com/en/help/getting-started) - [Legnext API Documentation](https://docs.legnext.ai/api-reference) - [Community Forum](https://community.make.com) ## Need Help? If you need assistance with Make integration, reach out to our support team at support@legnext.ai --- # Changelog _Track updates, new features, and improvements to the Legnext AI API_ ### April 25, 2026 — _New Feature_ #### Midjourney V8.1 Support - **V8.1 Model**: Add `--v 8.1` to your prompt to use Midjourney's latest alpha model — HD is now the default output, with ~40% faster generation than V8 HD - **HD by default, no premium**: V8.1 produces native 2K images at the same cost as V8 SD (1x credits). The 4x premium that applied to V8 `--hd` does **not** apply to V8.1 - **Image prompts and image weights restored**: V8.1 supports image URLs in prompts and the `--iw` parameter for image weighting - **Prompt Shortener**: Prompts that exceed length limits are automatically shortened by Midjourney - **Improved Describe**: V8.1 produces longer, more detailed prompt descriptions - **Subscription gate**: V8.1 requires a Pro (Developer) subscription or higher, same as V8 - **Removed in V8.1**: `--q` / `--quality`, `--cref` / `--cw`, `--oref` / `--ow`, and `--no` (negative prompt) are no longer supported. Requests containing these flags will be rejected with a clear error - **V8.0 deprecation**: Midjourney plans to sunset V8.0 approximately 2 weeks after V8.1 stabilizes. Migrate `--v 8` prompts to `--v 8.1` to avoid disruption - **Same endpoints**: V8.1 uses the existing `/v1/diffusion`, `/v1/variation`, `/v1/reroll`, `/v1/remix`, `/v1/blend`, and `/v1/video-diffusion` endpoints — no integration changes required ### April 3, 2026 — _New Feature_ #### Midjourney V8 Support - **V8 Model**: Add `--v 8` to your prompt to use Midjourney's latest model — ~5x faster generation, native 2K HD resolution, dramatically improved text rendering, and accurate anatomy - **Native 2K with --hd**: V8 renders natively at 2K resolution. No upscale step needed. Use `--hd` for high-resolution output (4x credit cost) - **New --oref parameter**: Omni Reference replaces `--cref` in V8, handling both person likeness and object form in a single parameter - **Enhanced coherence with --q 4**: New quality mode for complex scenes with many elements (4x credit cost) - **V8 Blend**: Blend endpoint now uses V8 natively for improved results - **Full follow-up support**: Variation, reroll, remix, and animate all work on V8-generated images - **Backward compatible**: Your existing V7 personalization profiles and style references work in V8 ### December 17, 2025 — _New Feature_ #### Topaz Integration Released - **[Topaz Upscale API](https://docs.legnext.ai/api-reference/enhancement/topaz-upscale)**: New `/v1/enhance-upscale` endpoint for ultra-high resolution image enhancement (up to 12K) using Topaz Labs AI technology - **Improved Parameter Organization**: Clear input method options (direct image URL or Midjourney task) with intuitive common parameters grouping - **Transparent Pricing**: Enhanced resolution options table with cost breakdown and recommended use cases for each resolution tier ### October 20, 2025 — _SDK Release_ #### Python SDK Released - **Official Python SDK**: Available on PyPI as `legnext` - **Complete Documentation**: New SDKs tab with guides, API reference, and examples - **Features**: Type hints, async support, webhook callbacks, error handling ### October 10, 2025 — _New releases_ #### New API endpoints - **/blend**: Easily blend images together using Midjourney's /blend command - **/describe**: Writes four example prompts based on an image you upload - **/shorten**: Submit a long prompt and receive suggestions on how to make it more concise ### October 9, 2025 — _Improvements_ #### Response structure enhancements - **4-grid image display**: Enhanced response structure to support 4-grid image display for /imagine tasks, providing better visualization of generated image variations #### Service optimization - **Temporary API endpoint suspension**: The following endpoints are temporarily paused: - /upload-paint - /retexture - /remove-background - /enhance These endpoints will be restored promptly after optimization is complete. ---