{"id":"4d79bcd0-da99-457f-94f8-185a5bf840f3","entityType":"agent","slug":"clawhub-adhikjoshi-modelslab","name":"Modelslab : Generate Video, Images, LLMs using CLI and APIs","canonicalUrl":"https://www.xpersona.co/agent/clawhub-adhikjoshi-modelslab","canonicalPath":"/agent/clawhub-adhikjoshi-modelslab","generatedAt":"2026-10-14T06:38:39.931Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-12T02:32:36.252Z","emptyReason":null},"description":"Access ModelsLab's full AI platform via CLI and APIs to generate images, videos, audio, 3D models, deepfakes, manage accounts, billing, and discover AI models.","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 954 downloads reported by the source. Last updated 10/12/2026.","installCommand":"clawhub skill install s177qwwwne234qs95ksymtyrqd885rha:modelslab","sourceUrl":"https://clawhub.ai/adhikjoshi/modelslab","homepage":"https://clawhub.ai/adhikjoshi/skills/modelslab","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/adhikjoshi/modelslab","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/adhikjoshi/skills/modelslab","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":60,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Modelslab : Generate Video, Images, LLMs using CLI and APIs technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-12T02:32:36.252Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-12T02:32:36.252Z","emptyReason":null},"stars":null,"forks":null,"downloads":954,"likes":null,"task":null,"library":null,"packageName":null,"latestVersion":"1.0.0","tractionLabel":"954 downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-12T02:32:36.238Z","emptyReason":null},"lastUpdatedAt":"2026-10-12T02:32:36.252Z","lastCrawledAt":"2026-10-12T02:32:36.238Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-13T02:32:36.238Z","lastVerifiedAt":null,"highlights":[{"version":"1.0.0","createdAt":"2026-03-04T20:03:38.830Z","changelog":"Initial release of the ModelsLab agent skills. - Provides official agent skills for ModelsLab's comprehensive AI API platform. - Enables image, video, audio, 3D, deepfake, and interior design AI generation. - Adds account management, billing, model discovery, webhooks, and SDK usage skills. - Includes installation instructions and example usage prompts. - Links to documentation, dashboard, and support resources.","fileCount":16,"zipByteSize":57304}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s177qwwwne234qs95ksymtyrqd885rha:modelslab","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s177qwwwne234qs95ksymtyrqd885rha:modelslab` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/adhikjoshi/modelslab before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-adhikjoshi-modelslab/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-adhikjoshi-modelslab/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-adhikjoshi-modelslab/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-adhikjoshi-modelslab/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-adhikjoshi-modelslab/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-adhikjoshi-modelslab/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-14T06:38:39.931Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-adhikjoshi-modelslab/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-adhikjoshi-modelslab/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-adhikjoshi-modelslab/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-adhikjoshi-modelslab/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-12T02:32:36.252Z","emptyReason":null},"readme":"Skill: Modelslab : Generate Video, Images, LLMs using CLI and APIs\n\nOwner: adhikjoshi\n\nSummary: Access ModelsLab's full AI platform via CLI and APIs to generate images, videos, audio, 3D models, deepfakes, manage accounts, billing, and discover AI models.\n\nTags: latest:1.0.0\n\nVersion history:\n\nv1.0.0 | 2026-03-04T20:03:38.830Z | user\n\nInitial release of the ModelsLab agent skills.\n\n- Provides official agent skills for ModelsLab's comprehensive AI API platform.\n- Enables image, video, audio, 3D, deepfake, and interior design AI generation.\n- Adds account management, billing, model discovery, webhooks, and SDK usage skills.\n- Includes installation instructions and example usage prompts.\n- Links to documentation, dashboard, and support resources.\n\nArchive index:\n\nArchive v1.0.0: 16 files, 57304 bytes\n\nFiles: 3d-generation/SKILL.md (9311b), account-management/SKILL.md (19585b), audio-generation/SKILL.md (10517b), billing-subscriptions/SKILL.md (28856b), chat-generation/SKILL.md (8630b), deepfake/SKILL.md (11620b), image-editing/SKILL.md (11284b), image-generation/SKILL.md (8895b), interior-design/SKILL.md (13569b), model-discovery/SKILL.md (11712b), README.md (6061b), sdk-usage/SKILL.md (13430b), Skills.md (6061b), video-generation/SKILL.md (9656b), webhooks/SKILL.md (13806b), _meta.json (128b)\n\nFile v1.0.0:3d-generation/SKILL.md\n\n---\nname: modelslab-3d-generation\ndescription: Generate 3D models and objects from text prompts or images using ModelsLab's 3D API. Transform 2D images into 3D representations or create 3D objects from text descriptions.\n---\n\n# ModelsLab 3D Generation\n\nTransform text descriptions and 2D images into 3D models using AI-powered 3D generation.\n\n## When to Use This Skill\n\n- Generate 3D models from text descriptions\n- Convert 2D images to 3D representations\n- Create 3D assets for games or applications\n- Prototype 3D objects quickly\n- Generate 3D product mockups\n- Create 3D characters from photos\n\n## Available Endpoints\n\n### Text to 3D\n`POST https://modelslab.com/api/v6/3d/text_to_3d`\n\n### Image to 3D\n`POST https://modelslab.com/api/v6/3d/image_to_3d`\n\n## Text to 3D\n\n```python\nimport requests\nimport time\n\ndef text_to_3d(prompt, api_key, num_inference_steps=50):\n    \"\"\"Generate a 3D object from a text prompt.\n\n    Args:\n        prompt: Text description of the 3D object\n        api_key: Your ModelsLab API key\n        num_inference_steps: Quality (higher = better, slower)\n\n    Returns:\n        URL of the 3D model file\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/3d/text_to_3d\",\n        json={\n            \"key\": api_key,\n            \"prompt\": prompt,\n            \"num_inference_steps\": num_inference_steps\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"error\":\n        raise Exception(f\"Error: {data['message']}\")\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n\n    # 3D generation is async - poll for results\n    request_id = data[\"id\"]\n    print(f\"3D generation started... Request ID: {request_id}\")\n    print(f\"ETA: {data.get('eta', 'unknown')} seconds\")\n\n    return poll_3d_result(request_id, api_key)\n\ndef poll_3d_result(request_id, api_key, timeout=600):\n    \"\"\"Poll for 3D generation results.\"\"\"\n    start_time = time.time()\n\n    while time.time() - start_time < timeout:\n        fetch = requests.post(\n            f\"https://modelslab.com/api/v6/3d/fetch/{request_id}\",\n            json={\"key\": api_key}\n        )\n        result = fetch.json()\n\n        if result[\"status\"] == \"success\":\n            return result[\"output\"][0]\n        elif result[\"status\"] == \"failed\":\n            raise Exception(result.get(\"message\", \"Generation failed\"))\n\n        print(f\"Status: processing... ({int(time.time() - start_time)}s elapsed)\")\n        time.sleep(10)\n\n    raise Exception(\"Timeout waiting for 3D generation\")\n\n# Usage\nmodel_url = text_to_3d(\n    \"A medieval sword with ornate handle and detailed engravings\",\n    \"your_api_key\",\n    num_inference_steps=50\n)\nprint(f\"3D model ready: {model_url}\")\n```\n\n## Image to 3D\n\n```python\ndef image_to_3d(image_url, api_key):\n    \"\"\"Convert a 2D image into a 3D model.\n\n    Args:\n        image_url: URL of the 2D image\n        api_key: Your ModelsLab API key\n\n    Returns:\n        URL of the generated 3D model\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/3d/image_to_3d\",\n        json={\n            \"key\": api_key,\n            \"image\": image_url\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"error\":\n        raise Exception(f\"Error: {data['message']}\")\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n\n    # Poll for results\n    request_id = data[\"id\"]\n    print(f\"Converting image to 3D... Request ID: {request_id}\")\n\n    return poll_3d_result(request_id, api_key)\n\n# Convert product photo to 3D\nmodel_url = image_to_3d(\n    \"https://example.com/product-photo.jpg\",\n    \"your_api_key\"\n)\nprint(f\"3D model: {model_url}\")\n```\n\n## Using Webhooks\n\n```python\ndef generate_3d_with_webhook(prompt, api_key, webhook_url, track_id):\n    \"\"\"Generate 3D model and receive results via webhook.\"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/3d/text_to_3d\",\n        json={\n            \"key\": api_key,\n            \"prompt\": prompt,\n            \"num_inference_steps\": 50,\n            \"webhook\": webhook_url,\n            \"track_id\": track_id\n        }\n    )\n\n    data = response.json()\n    print(f\"Request submitted: {data['id']}\")\n    return data[\"id\"]\n\n# Usage\nrequest_id = generate_3d_with_webhook(\n    \"A futuristic sci-fi weapon\",\n    \"your_api_key\",\n    \"https://yourserver.com/webhook/3d\",\n    \"model_001\"\n)\n```\n\n## Key Parameters\n\n| Parameter | Description | Recommended Values |\n|-----------|-------------|-------------------|\n| `prompt` | Text description of 3D object | Be specific about shape, style, details |\n| `image` | 2D image URL for conversion | Clear, well-lit product photo |\n| `num_inference_steps` | Quality vs speed | 30 (fast), 50 (balanced), 100 (quality) |\n| `webhook` | Async callback URL | Your server endpoint |\n| `track_id` | Request identifier | Unique ID for tracking |\n\n## Best Practices\n\n### 1. Craft Effective 3D Prompts\n```\n✗ Bad: \"a chair\"\n✓ Good: \"A modern office chair with ergonomic design, armrests, five wheels, mesh back\"\n\nInclude: Type, style, materials, key features, details\n```\n\n### 2. Image to 3D Requirements\n- Use clear, well-lit images\n- Single object on plain background works best\n- Multiple angles help (if supported)\n- High resolution input recommended\n\n### 3. Set Realistic Expectations\n- 3D generation takes 5-15 minutes\n- Quality depends on input quality\n- Complex objects may need refinement\n- Best for simple to moderate complexity\n\n### 4. Always Use Async Pattern\n```python\n# 3D generation is ALWAYS async\nif data[\"status\"] == \"processing\":\n    result = poll_3d_result(data[\"id\"], api_key)\n```\n\n### 5. Handle Long Wait Times\n```python\n# Use longer timeouts for 3D\npoll_3d_result(request_id, api_key, timeout=900)  # 15 minutes\n\n# Or use webhooks\ngenerate_3d_with_webhook(prompt, api_key, webhook_url, track_id)\n```\n\n## Common Use Cases\n\n### Game Assets\n\n```python\n# Generate weapon\nsword = text_to_3d(\n    \"Fantasy sword with glowing blue blade, ornate gold handle, medieval style\",\n    api_key,\n    num_inference_steps=75\n)\n\n# Generate character prop\nshield = text_to_3d(\n    \"Round wooden shield with iron rim and clan emblem in center\",\n    api_key\n)\n```\n\n### Product Prototyping\n\n```python\n# Create product mockup\nprototype = text_to_3d(\n    \"Modern wireless earbuds with charging case, minimalist design, matte white finish\",\n    api_key,\n    num_inference_steps=100\n)\n```\n\n### E-commerce 3D Models\n\n```python\n# Convert product photo to 3D\ndef create_product_3d_view(product_image_url, api_key):\n    \"\"\"Generate 3D model from product photo.\"\"\"\n    model = image_to_3d(product_image_url, api_key)\n    print(f\"3D product view ready: {model}\")\n    return model\n\nproduct_3d = create_product_3d_view(\n    \"https://example.com/product.jpg\",\n    api_key\n)\n```\n\n### Architectural Elements\n\n```python\n# Generate furniture\nfurniture = text_to_3d(\n    \"Modern minimalist coffee table, glass top, wooden legs, Scandinavian design\",\n    api_key\n)\n\n# Generate decorations\nvase = text_to_3d(\n    \"Ceramic vase with geometric pattern, blue and white colors, modern style\",\n    api_key\n)\n```\n\n## Batch Generation\n\n```python\ndef generate_multiple_3d_models(prompts, api_key):\n    \"\"\"Generate multiple 3D models in batch.\"\"\"\n    request_ids = []\n\n    # Submit all requests\n    for i, prompt in enumerate(prompts):\n        response = requests.post(\n            \"https://modelslab.com/api/v6/3d/text_to_3d\",\n            json={\n                \"key\": api_key,\n                \"prompt\": prompt,\n                \"webhook\": \"https://yourserver.com/webhook/3d\",\n                \"track_id\": f\"batch_{i}\"\n            }\n        )\n        request_ids.append(response.json()[\"id\"])\n        print(f\"Submitted: {prompt}\")\n\n    print(f\"All {len(prompts)} requests submitted\")\n    return request_ids\n\n# Generate multiple assets\nmodels = generate_multiple_3d_models([\n    \"Medieval sword\",\n    \"Knight's helmet\",\n    \"Wooden shield\",\n    \"Battle axe\"\n], api_key)\n```\n\n## Error Handling\n\n```python\ntry:\n    model = text_to_3d(prompt, api_key)\n    print(f\"3D model generated: {model}\")\nexcept Exception as e:\n    print(f\"3D generation failed: {e}\")\n    # Log error, retry with simpler prompt, notify user\n```\n\n## Output Formats\n\nThe API returns 3D model files in common formats:\n- `.glb` (glTF Binary)\n- `.obj` (Wavefront OBJ)\n- `.fbx` (Filmbox)\n\nCheck the response for specific format details.\n\n## Performance Tips\n\n1. **Use Webhooks**: Don't poll continuously\n2. **Batch Similar Requests**: Generate multiple models together\n3. **Cache Results**: Store generated models for reuse\n4. **Start Simple**: Test with simple objects first\n5. **Monitor Generation Time**: Track and optimize\n\n## Enterprise API\n\nFor dedicated resources:\n\n```python\n# Enterprise endpoints\ntext_to_3d_url = \"https://modelslab.com/api/v1/enterprise/3d/text_to_3d\"\nimage_to_3d_url = \"https://modelslab.com/api/v1/enterprise/3d/image_to_3d\"\n```\n\n## Resources\n\n- **3D API Documentation**: https://docs.modelslab.com/3d-api/overview\n- **Text to 3D**: https://docs.modelslab.com/3d-api/text-to-3d\n- **Image to 3D**: https://docs.modelslab.com/3d-api/image-to-3d\n- **Get API Key**: https://modelslab.com/dashboard\n\n## Related Skills\n\n- `modelslab-image-generation` - Generate images for image-to-3D\n- `modelslab-webhooks` - Handle async 3D generation\n- `modelslab-sdk-usage` - Use official SDKs\n\nFile v1.0.0:account-management/SKILL.md\n\n---\nname: modelslab-account-management\ndescription: Manage ModelsLab accounts programmatically — signup, login, token management, profile updates, API key CRUD, and team member management. Uses the Agent Control Plane API with bearer token auth.\n---\n\n# ModelsLab Account Management\n\nManage the full ModelsLab account lifecycle via the Agent Control Plane API — authentication, tokens, profile, API keys, and teams.\n\n## When to Use This Skill\n\n- Sign up or log in to ModelsLab programmatically\n- Create and manage API keys for generation endpoints\n- Update user profile, password, or social links\n- Manage access tokens (list, revoke, switch team accounts)\n- Invite, update, or remove team members\n- Build agent workflows that need account bootstrapping\n\n## Authentication\n\nThe Agent Control Plane uses **bearer tokens** (not API keys). Some endpoints (signup, login, forgot-password) work without a token.\n\n```\nBase URL: https://modelslab.com/api/agents/v1\nAuthorization: Bearer <agent_access_token>\n```\n\n## Auth: Signup & Login\n\n### Sign Up\n\n```python\nimport requests\n\ndef signup(email, password, name=None):\n    \"\"\"Create a new ModelsLab account.\"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/agents/v1/auth/signup\",\n        json={\n            \"email\": email,\n            \"password\": password,\n            \"name\": name or \"\"\n        }\n    )\n    data = response.json()\n    if \"error\" in data:\n        raise Exception(data[\"error\"])\n    return data[\"data\"]  # Contains access_token\n\n# Usage\nresult = signup(\"agent@example.com\", \"securepass123\", \"My Agent\")\ntoken = result[\"access_token\"]\nprint(f\"Signed up! Token: {token}\")\n```\n\n### Log In\n\n```python\ndef login(email, password, token_expiry=\"1_month\"):\n    \"\"\"Log in and get a bearer token.\n\n    Args:\n        token_expiry: \"1_week\", \"1_month\" (default), \"3_months\", \"never\"\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/agents/v1/auth/login\",\n        json={\n            \"email\": email,\n            \"password\": password,\n            \"device_name\": \"my-agent\",\n            \"token_expiry\": token_expiry\n        }\n    )\n    data = response.json()\n    if \"error\" in data:\n        raise Exception(data[\"error\"])\n    return data[\"data\"][\"access_token\"]\n\n# Usage\ntoken = login(\"agent@example.com\", \"securepass123\")\n```\n\n### Logout\n\n```python\ndef logout(token):\n    \"\"\"Revoke current token.\"\"\"\n    requests.post(\n        \"https://modelslab.com/api/agents/v1/auth/logout\",\n        headers={\"Authorization\": f\"Bearer {token}\"}\n    )\n\ndef logout_all(token):\n    \"\"\"Revoke all tokens for this account.\"\"\"\n    requests.post(\n        \"https://modelslab.com/api/agents/v1/auth/logout-all\",\n        headers={\"Authorization\": f\"Bearer {token}\"}\n    )\n```\n\n### Verify Email (Headless)\n\nAfter signup, the user receives a `verification_code` via email. Verify without a browser:\n\n```python\ndef verify_email(verification_code):\n    \"\"\"Verify email with the code from the verification email.\n\n    Returns an access_token and api_key — no browser required.\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/agents/v1/auth/verify-email\",\n        json={\"verification_code\": verification_code}\n    )\n    data = response.json()\n    if \"error\" in data:\n        raise Exception(data[\"error\"])\n    return data[\"data\"]\n\n# Usage — complete headless signup flow\nresult = verify_email(\"the_code_from_email\")\ntoken = result[\"access_token\"]\napi_key = result[\"api_key\"]\nprint(f\"Verified! Token: {token}, API Key: {api_key}\")\n```\n\n### Refresh Token\n\nRotate the current bearer token without re-authenticating:\n\n```python\ndef refresh_token(token, token_expiry=\"1_month\"):\n    \"\"\"Refresh/rotate the current access token.\n\n    The old token is revoked and a new one is issued.\n\n    Args:\n        token_expiry: \"1_week\", \"1_month\" (default), \"3_months\", \"never\"\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/agents/v1/auth/refresh\",\n        headers={\"Authorization\": f\"Bearer {token}\"},\n        json={\"token_expiry\": token_expiry}\n    )\n    data = response.json()\n    if \"error\" in data:\n        raise Exception(data[\"error\"])\n    return data[\"data\"][\"access_token\"]\n\n# Usage — rotate token before it expires\nnew_token = refresh_token(old_token, token_expiry=\"1_month\")\n```\n\n### Password Reset\n\n```python\ndef forgot_password(email):\n    \"\"\"Request a password reset email.\"\"\"\n    requests.post(\n        \"https://modelslab.com/api/agents/v1/auth/forgot-password\",\n        json={\"email\": email}\n    )\n\ndef reset_password(email, token, new_password):\n    \"\"\"Reset password using the reset token from email.\"\"\"\n    requests.post(\n        \"https://modelslab.com/api/agents/v1/auth/reset-password\",\n        json={\n            \"email\": email,\n            \"token\": token,\n            \"password\": new_password,\n            \"password_confirmation\": new_password\n        }\n    )\n```\n\n## Token Management\n\n```python\ndef make_headers(token):\n    return {\"Authorization\": f\"Bearer {token}\"}\n\ndef list_tokens(token):\n    \"\"\"List all active tokens.\"\"\"\n    resp = requests.get(\n        \"https://modelslab.com/api/agents/v1/auth/tokens\",\n        headers=make_headers(token)\n    )\n    return resp.json()[\"data\"]\n\ndef revoke_token(token, token_id):\n    \"\"\"Revoke a specific token by ID.\"\"\"\n    requests.delete(\n        f\"https://modelslab.com/api/agents/v1/auth/tokens/{token_id}\",\n        headers=make_headers(token)\n    )\n\ndef revoke_other_tokens(token):\n    \"\"\"Revoke all tokens except the current one.\"\"\"\n    requests.post(\n        \"https://modelslab.com/api/agents/v1/auth/tokens/revoke-others\",\n        headers=make_headers(token)\n    )\n\ndef switch_account(token, team_username):\n    \"\"\"Switch to a team account context. Returns new token.\"\"\"\n    resp = requests.post(\n        \"https://modelslab.com/api/agents/v1/auth/switch-account\",\n        headers=make_headers(token),\n        json={\"account_username\": team_username}\n    )\n    return resp.json()[\"data\"][\"access_token\"]\n```\n\n## Profile Management\n\n### Get Profile\n\n```python\ndef get_profile(token):\n    \"\"\"Get the authenticated user's profile.\"\"\"\n    resp = requests.get(\n        \"https://modelslab.com/api/agents/v1/me\",\n        headers=make_headers(token)\n    )\n    return resp.json()[\"data\"]\n\n# Usage\nprofile = get_profile(token)\nprint(f\"Name: {profile['name']}, Email: {profile['email']}\")\nprint(f\"Wallet: ${profile.get('wallet_balance', 0)}\")\n```\n\n### Update Profile\n\n```python\ndef update_profile(token, name=None, username=None, about_me=None):\n    \"\"\"Update profile fields.\"\"\"\n    payload = {}\n    if name: payload[\"name\"] = name\n    if username: payload[\"username\"] = username\n    if about_me: payload[\"about_me\"] = about_me\n\n    resp = requests.patch(\n        \"https://modelslab.com/api/agents/v1/me\",\n        headers=make_headers(token),\n        json=payload\n    )\n    return resp.json()[\"data\"]\n\ndef update_password(token, current_password, new_password):\n    \"\"\"Change account password.\"\"\"\n    requests.patch(\n        \"https://modelslab.com/api/agents/v1/me/password\",\n        headers=make_headers(token),\n        json={\n            \"current_password\": current_password,\n            \"password\": new_password,\n            \"password_confirmation\": new_password\n        }\n    )\n\ndef update_socials(token, github=None, twitter=None, discord=None):\n    \"\"\"Update social media links.\"\"\"\n    payload = {}\n    if github: payload[\"github\"] = github\n    if twitter: payload[\"twitter\"] = twitter\n    if discord: payload[\"discord\"] = discord\n\n    requests.patch(\n        \"https://modelslab.com/api/agents/v1/me/socials\",\n        headers=make_headers(token),\n        json=payload\n    )\n\ndef update_preferences(token, nsfw_content=None, wallet_notification_enabled=None):\n    \"\"\"Update account preferences.\"\"\"\n    payload = {}\n    if nsfw_content is not None: payload[\"nsfw_content\"] = nsfw_content\n    if wallet_notification_enabled is not None:\n        payload[\"wallet_notification_enabled\"] = wallet_notification_enabled\n\n    requests.patch(\n        \"https://modelslab.com/api/agents/v1/me/preferences\",\n        headers=make_headers(token),\n        json=payload\n    )\n```\n\n## API Key Management\n\nAPI keys are used for generation endpoints (`/api/v6`, `/api/v7`, `/api/v8`).\n\n### List API Keys\n\n```python\ndef list_api_keys(token):\n    \"\"\"List all API keys.\"\"\"\n    resp = requests.get(\n        \"https://modelslab.com/api/agents/v1/api-keys\",\n        headers=make_headers(token)\n    )\n    return resp.json()[\"data\"]\n```\n\n### Create API Key\n\n```python\ndef create_api_key(token, name, notes=None):\n    \"\"\"Create a new API key for generation endpoints.\n\n    Returns the full key — store it securely, it won't be shown again.\n    \"\"\"\n    payload = {\"name\": name}\n    if notes: payload[\"notes\"] = notes\n\n    resp = requests.post(\n        \"https://modelslab.com/api/agents/v1/api-keys\",\n        headers=make_headers(token),\n        json=payload\n    )\n    return resp.json()[\"data\"]\n\n# Usage\nkey_data = create_api_key(token, \"production-key\", notes=\"Used by CI/CD\")\napi_key = key_data[\"key\"]\nprint(f\"API Key: {api_key}\")\n```\n\n### Get, Update, Delete API Key\n\n```python\ndef get_api_key(token, key_id):\n    \"\"\"Get details of a specific API key.\"\"\"\n    resp = requests.get(\n        f\"https://modelslab.com/api/agents/v1/api-keys/{key_id}\",\n        headers=make_headers(token)\n    )\n    return resp.json()[\"data\"]\n\ndef update_api_key(token, key_id, name=None, notes=None):\n    \"\"\"Update an API key's name or notes.\"\"\"\n    payload = {}\n    if name: payload[\"name\"] = name\n    if notes: payload[\"notes\"] = notes\n\n    resp = requests.put(\n        f\"https://modelslab.com/api/agents/v1/api-keys/{key_id}\",\n        headers=make_headers(token),\n        json=payload\n    )\n    return resp.json()[\"data\"]\n\ndef delete_api_key(token, key_id):\n    \"\"\"Delete an API key.\"\"\"\n    requests.delete(\n        f\"https://modelslab.com/api/agents/v1/api-keys/{key_id}\",\n        headers=make_headers(token)\n    )\n```\n\n## Team Management\n\n### List Team Members\n\n```python\ndef list_team_members(token):\n    \"\"\"List all team members and pending invites.\"\"\"\n    resp = requests.get(\n        \"https://modelslab.com/api/agents/v1/teams\",\n        headers=make_headers(token)\n    )\n    return resp.json()[\"data\"]\n```\n\n### Invite Team Member\n\n```python\ndef invite_team_member(token, email):\n    \"\"\"Send a team invite to an email address.\"\"\"\n    resp = requests.post(\n        \"https://modelslab.com/api/agents/v1/teams\",\n        headers=make_headers(token),\n        json={\"email\": email}\n    )\n    return resp.json()[\"data\"]\n\n# Usage\ninvite_team_member(token, \"colleague@example.com\")\n```\n\n### Manage Members\n\n```python\ndef get_team_member(token, member_id):\n    \"\"\"Get details of a team member.\"\"\"\n    resp = requests.get(\n        f\"https://modelslab.com/api/agents/v1/teams/{member_id}\",\n        headers=make_headers(token)\n    )\n    return resp.json()[\"data\"]\n\ndef update_team_member(token, member_id, role=None, permissions=None):\n    \"\"\"Update a team member's role or permissions.\"\"\"\n    payload = {}\n    if role: payload[\"role\"] = role\n    if permissions: payload[\"permissions\"] = permissions\n\n    resp = requests.put(\n        f\"https://modelslab.com/api/agents/v1/teams/{member_id}\",\n        headers=make_headers(token),\n        json=payload\n    )\n    return resp.json()[\"data\"]\n\ndef remove_team_member(token, member_id):\n    \"\"\"Remove a member from the team.\"\"\"\n    requests.delete(\n        f\"https://modelslab.com/api/agents/v1/teams/{member_id}\",\n        headers=make_headers(token)\n    )\n\ndef resend_invite(token, member_id):\n    \"\"\"Resend a pending team invite.\"\"\"\n    requests.post(\n        f\"https://modelslab.com/api/agents/v1/teams/{member_id}/resend-invite\",\n        headers=make_headers(token)\n    )\n\ndef accept_invite(token, invite_id):\n    \"\"\"Accept a team invitation.\"\"\"\n    requests.post(\n        f\"https://modelslab.com/api/agents/v1/teams/invitations/{invite_id}/accept\",\n        headers=make_headers(token)\n    )\n```\n\n## Complete Agent Bootstrap Example\n\n```python\nimport requests\n\nclass ModelsLabAgent:\n    \"\"\"Bootstrap a ModelsLab account for an AI agent.\"\"\"\n\n    BASE = \"https://modelslab.com/api/agents/v1\"\n\n    def __init__(self):\n        self.token = None\n        self.api_key = None\n\n    def _headers(self):\n        return {\"Authorization\": f\"Bearer {self.token}\"}\n\n    def login(self, email, password):\n        \"\"\"Step 1: Authenticate.\"\"\"\n        resp = requests.post(f\"{self.BASE}/auth/login\", json={\n            \"email\": email,\n            \"password\": password,\n            \"token_expiry\": \"1_month\"\n        })\n        self.token = resp.json()[\"data\"][\"access_token\"]\n        return self\n\n    def get_or_create_api_key(self, name=\"agent-key\"):\n        \"\"\"Step 2: Get existing key or create one.\"\"\"\n        keys = requests.get(\n            f\"{self.BASE}/api-keys\",\n            headers=self._headers()\n        ).json()[\"data\"]\n\n        for key in keys:\n            if key[\"name\"] == name:\n                self.api_key = key[\"key\"]\n                return self.api_key\n\n        new_key = requests.post(\n            f\"{self.BASE}/api-keys\",\n            headers=self._headers(),\n            json={\"name\": name}\n        ).json()[\"data\"]\n\n        self.api_key = new_key[\"key\"]\n        return self.api_key\n\n    def check_ready(self):\n        \"\"\"Step 3: Verify account is ready for generation.\"\"\"\n        profile = requests.get(\n            f\"{self.BASE}/me\",\n            headers=self._headers()\n        ).json()[\"data\"]\n\n        print(f\"Account: {profile['name']} ({profile['email']})\")\n        print(f\"API Key: {self.api_key[:8]}...\")\n        return True\n\n# Usage\nagent = ModelsLabAgent()\nagent.login(\"agent@example.com\", \"password\")\nagent.get_or_create_api_key(\"production\")\nagent.check_ready()\n\n# Now use agent.api_key with generation endpoints\n```\n\n## Headless Agent Flow (No Browser Required)\n\nThe complete flow for agents that need to sign up, verify, add payment, subscribe, and generate content without any browser interaction. See `modelslab-billing-subscriptions` for all three payment paths (headless, setup intent, human-assisted).\n\n```python\nimport requests\n\nBASE = \"https://modelslab.com/api/agents/v1\"\n\n# Fetch Stripe publishable key dynamically\nconfig_resp = requests.get(f\"{BASE}/billing/stripe-config\",\n    headers={\"Authorization\": f\"Bearer {token}\"})\nSTRIPE_PK = config_resp.json()[\"publishable_key\"]\n\n# 1. Sign up\nsignup_resp = requests.post(f\"{BASE}/auth/signup\", json={\n    \"email\": \"agent@example.com\",\n    \"password\": \"securepass123\",\n    \"name\": \"My Agent\"\n})\n# -> User receives verification_code in email\n\n# 2. Verify email with code from email (no browser needed)\nverify_resp = requests.post(f\"{BASE}/auth/verify-email\", json={\n    \"verification_code\": \"the_code_from_email\"\n})\ntoken = verify_resp.json()[\"data\"][\"access_token\"]\napi_key = verify_resp.json()[\"data\"][\"api_key\"]\nhdrs = {\"Authorization\": f\"Bearer {token}\"}\n\n# 3a. Option A: Headless card tokenization via Stripe API (recommended)\n# Or fetch key dynamically: GET /billing/stripe-config\npm_resp = requests.post(\n    \"https://api.stripe.com/v1/payment_methods\",\n    auth=(STRIPE_PK, \"\"),\n    data={\n        \"type\": \"card\",\n        \"card[number]\": \"4242424242424242\",\n        \"card[exp_month]\": 12,\n        \"card[exp_year]\": 2027,\n        \"card[cvc]\": \"123\",\n    }\n)\npm_id = pm_resp.json()[\"id\"]\n\n# 3b. Option B: Setup Intent flow (save card for future use)\n# setup_resp = requests.post(f\"{BASE}/billing/setup-intent\", headers=hdrs)\n# -> Confirm with Stripe API, then use the resulting pm_id\n\n# 3c. Option C: Human-assisted payment link\n# link = requests.post(f\"{BASE}/billing/payment-link\", headers=hdrs, json={\n#     \"purpose\": \"subscribe\", \"plan_id\": 123\n# }).json()[\"data\"]\n# -> Forward link[\"payment_url\"] to human, then confirm-checkout\n\n# 4. Attach the payment method\nrequests.post(f\"{BASE}/billing/payment-methods\", headers=hdrs, json={\n    \"payment_method_id\": pm_id,\n    \"make_default\": True\n})\n\n# 5. Subscribe headlessly with payment_method_id (no Checkout redirect)\nsub_resp = requests.post(f\"{BASE}/subscriptions\", headers=hdrs, json={\n    \"plan_id\": 123,\n    \"payment_method_id\": pm_id\n})\n\n# 6. Generate content using existing APIs with the api_key from step 2\ngen_resp = requests.post(\"https://modelslab.com/api/v6/images/text2img\", json={\n    \"key\": api_key,\n    \"model_id\": \"flux-dev\",\n    \"prompt\": \"A sunset over mountains\",\n    \"width\": 1024,\n    \"height\": 1024\n})\n```\n\n## MCP Server Access\n\nThese same capabilities are available via the Agent Control Plane MCP server:\n- **URL**: `https://modelslab.com/mcp/agents`\n- **Auth**: `Authorization: Bearer <token>`\n- **Tools**: `agent-auth`, `agent-tokens`, `agent-profile`, `agent-api-keys`, `agent-teams`\n\nSee: https://docs.modelslab.com/mcp-web-api/agent-control-plane\n\n## API Endpoints Reference\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| POST | `/auth/signup` | Create account |\n| POST | `/auth/login` | Get bearer token |\n| POST | `/auth/verify-email` | Verify email with code (headless) |\n| POST | `/auth/refresh` | Refresh/rotate access token |\n| POST | `/auth/logout` | Revoke current token |\n| POST | `/auth/logout-all` | Revoke all tokens |\n| POST | `/auth/forgot-password` | Request reset email |\n| POST | `/auth/reset-password` | Reset with token |\n| POST | `/auth/resend-verification` | Resend verification email |\n| GET | `/auth/tokens` | List active tokens |\n| DELETE | `/auth/tokens/{id}` | Revoke specific token |\n| POST | `/auth/tokens/revoke-others` | Revoke other tokens |\n| POST | `/auth/switch-account` | Switch team context |\n| GET | `/me` | Get profile |\n| PATCH | `/me` | Update profile |\n| PATCH | `/me/password` | Change password |\n| PATCH | `/me/socials` | Update social links |\n| PATCH | `/me/preferences` | Update preferences |\n| GET | `/api-keys` | List API keys |\n| POST | `/api-keys` | Create API key |\n| GET | `/api-keys/{id}` | Get API key |\n| PUT | `/api-keys/{id}` | Update API key |\n| DELETE | `/api-keys/{id}` | Delete API key |\n| GET | `/teams` | List team members |\n| POST | `/teams` | Invite member |\n| GET | `/teams/{id}` | Get member details |\n| PUT | `/teams/{id}` | Update member |\n| DELETE | `/teams/{id}` | Remove member |\n| POST | `/teams/{id}/resend-invite` | Resend invite |\n| POST | `/teams/invitations/{id}/accept` | Accept invite |\n\n## Best Practices\n\n### 1. Store Tokens Securely\n```python\nimport os\n# Use environment variables, not hardcoded values\ntoken = os.getenv(\"MODELSLAB_AGENT_TOKEN\")\n```\n\n### 2. Use Token Expiry Wisely\n```python\n# Short-lived for CI/CD\nlogin(email, password, token_expiry=\"1_week\")\n\n# Long-lived for persistent agents\nlogin(email, password, token_expiry=\"never\")\n```\n\n### 3. Create Descriptive API Keys\n```python\ncreate_api_key(token, \"staging-backend\", notes=\"Used by staging environment\")\ncreate_api_key(token, \"ci-tests\", notes=\"Used by GitHub Actions\")\n```\n\n### 4. Clean Up Old Tokens\n```python\n# Revoke all other tokens when rotating\nrevoke_other_tokens(token)\n```\n\n## Resources\n\n- **API Documentation**: https://docs.modelslab.com/agents-api/overview\n- **MCP Server**: https://docs.modelslab.com/mcp-web-api/agent-control-plane\n- **Dashboard**: https://modelslab.com/dashboard\n- **Discord**: https://discord.gg/modelslab\n\n## Related Skills\n\n- `modelslab-billing-subscriptions` - Billing, wallet, and subscription management\n- `modelslab-model-discovery` - Search models and check usage analytics\n- `modelslab-training` - Model training and fine-tuning\n- `modelslab-servers` - Deploy dedicated GPU servers\n- `modelslab-image-generation` - Use API keys for image generation\n\nFile v1.0.0:audio-generation/SKILL.md\n\n---\nname: modelslab-audio-generation\ndescription: Generate speech, music, and sound effects using ModelsLab's v7 Voice API. Supports text-to-speech, speech-to-text, speech-to-speech, music generation, sound effects, dubbing, song extension, and song inpainting via ElevenLabs and Inworld models.\n---\n\n# ModelsLab Audio Generation\n\nGenerate high-quality audio including speech, music, voice conversion, sound effects, and dubbing using AI.\n\n## When to Use This Skill\n\n- Convert text to natural-sounding speech (TTS)\n- Transcribe speech to text\n- Transform voice characteristics (speech-to-speech)\n- Generate music from text prompts\n- Create sound effects\n- Dub audio into different languages\n- Extend or inpaint songs\n- Build voice assistants or audiobooks\n\n## Available APIs (v7)\n\n### Voice Endpoints\n- **Text to Speech**: `POST https://modelslab.com/api/v7/voice/text-to-speech`\n- **Speech to Text**: `POST https://modelslab.com/api/v7/voice/speech-to-text`\n- **Speech to Speech**: `POST https://modelslab.com/api/v7/voice/speech-to-speech`\n- **Music Generation**: `POST https://modelslab.com/api/v7/voice/music-gen`\n- **Sound Generation**: `POST https://modelslab.com/api/v7/voice/sound-generation`\n- **Create Dubbing**: `POST https://modelslab.com/api/v7/voice/create-dubbing`\n- **Song Extender**: `POST https://modelslab.com/api/v7/voice/song-extender`\n- **Song Inpaint**: `POST https://modelslab.com/api/v7/voice/song-inpaint`\n- **Fetch Result**: `POST https://modelslab.com/api/v7/voice/fetch/{id}`\n\n> **Note**: v6 endpoints (`/api/v6/voice/text_to_speech`, etc.) still work but v7 is the current version. Parameter names have changed in v7 (e.g., `text` is now `prompt`, `audio` is now `init_audio`).\n\n## Discovering Audio Models\n\n```bash\n# Search audio/voice models\nmodelslab models search --feature audio_gen\n\n# Search by provider\nmodelslab models search --search \"eleven\"\n\n# Get model details\nmodelslab models detail --id eleven_multilingual_v2\n```\n\n## Audio Model IDs\n\n| model_id | Name | Use With |\n|----------|------|----------|\n| `eleven_multilingual_v2` | ElevenLabs Multilingual v2 | text-to-speech |\n| `eleven_english_sts_v2` | ElevenLabs Voice Changer | speech-to-speech |\n| `scribe_v1` | ElevenLabs Scribe | speech-to-text |\n| `eleven_sound_effect` | ElevenLabs Sound Effects | sound-generation |\n| `music_v1` | ElevenLabs Music | music-gen |\n| `inworld-tts-1` | Inworld TTS | text-to-speech |\n\n## Text to Speech\n\n```python\nimport requests\nimport time\n\ndef text_to_speech(text, api_key, voice_id=\"21m00Tcm4TlvDq8ikWAM\", model_id=\"eleven_multilingual_v2\"):\n    \"\"\"Convert text to speech.\n\n    Args:\n        text: The text to convert to speech\n        api_key: Your ModelsLab API key\n        voice_id: ElevenLabs voice ID (see Available Voices below)\n        model_id: TTS model to use\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v7/voice/text-to-speech\",\n        json={\n            \"key\": api_key,\n            \"prompt\": text,             # v7 uses \"prompt\" not \"text\"\n            \"voice_id\": voice_id,\n            \"model_id\": model_id\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n    elif data[\"status\"] == \"processing\":\n        return poll_audio_result(data[\"id\"], api_key)\n    else:\n        raise Exception(f\"Error: {data.get('message', 'Unknown error')}\")\n\n# Usage\naudio_url = text_to_speech(\n    \"Hello! Welcome to ModelsLab. This is a test of our text-to-speech API.\",\n    \"your_api_key\"\n)\nprint(f\"Audio URL: {audio_url}\")\n```\n\n## Speech to Text (Transcription)\n\n```python\ndef speech_to_text(audio_url, api_key, model_id=\"scribe_v1\"):\n    \"\"\"Transcribe speech from audio to text.\n\n    Args:\n        audio_url: URL of audio file (must be publicly accessible)\n        model_id: STT model to use\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v7/voice/speech-to-text\",\n        json={\n            \"key\": api_key,\n            \"init_audio\": audio_url,    # v7 uses \"init_audio\" not \"audio\"\n            \"model_id\": model_id\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n    elif data[\"status\"] == \"processing\":\n        return poll_audio_result(data[\"id\"], api_key)\n    else:\n        raise Exception(data.get(\"message\"))\n\n# Transcribe audio\nresult = speech_to_text(\n    \"https://example.com/speech.mp3\",\n    \"your_api_key\"\n)\nprint(f\"Transcription: {result}\")\n```\n\n## Speech to Speech (Voice Conversion)\n\n```python\ndef speech_to_speech(audio_url, voice_id, api_key, model_id=\"eleven_english_sts_v2\"):\n    \"\"\"Convert voice characteristics in audio.\n\n    Args:\n        audio_url: URL of the source audio\n        voice_id: Target ElevenLabs voice ID\n        model_id: Voice conversion model\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v7/voice/speech-to-speech\",\n        json={\n            \"key\": api_key,\n            \"init_audio\": audio_url,\n            \"voice_id\": voice_id,\n            \"model_id\": model_id\n        }\n    )\n\n    data = response.json()\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n    elif data[\"status\"] == \"processing\":\n        return poll_audio_result(data[\"id\"], api_key)\n```\n\n## Sound Effects Generation\n\n```python\ndef generate_sound_effect(description, api_key, model_id=\"eleven_sound_effect\"):\n    \"\"\"Generate a sound effect from a text description.\n\n    Args:\n        description: What sound to generate\n        model_id: Sound effects model\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v7/voice/sound-generation\",\n        json={\n            \"key\": api_key,\n            \"prompt\": description,\n            \"model_id\": model_id\n        }\n    )\n\n    data = response.json()\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n    elif data[\"status\"] == \"processing\":\n        return poll_audio_result(data[\"id\"], api_key)\n\n# Generate door slam sound\nsfx_url = generate_sound_effect(\n    \"Heavy wooden door slamming shut\",\n    \"your_api_key\"\n)\n```\n\n## Music Generation\n\n```python\ndef generate_music(prompt, api_key, model_id=\"music_v1\"):\n    \"\"\"Generate music from a text description.\n\n    Args:\n        prompt: Description of music style/mood\n        model_id: Music generation model\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v7/voice/music-gen\",\n        json={\n            \"key\": api_key,\n            \"prompt\": prompt,\n            \"model_id\": model_id\n        }\n    )\n\n    data = response.json()\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n    elif data[\"status\"] == \"processing\":\n        return poll_audio_result(data[\"id\"], api_key)\n\n# Generate background music\nmusic_url = generate_music(\n    \"Upbeat electronic music with a driving beat, perfect for a tech startup video\",\n    \"your_api_key\"\n)\nprint(f\"Music: {music_url}\")\n```\n\n## Polling for Async Results\n\n```python\ndef poll_audio_result(request_id, api_key, timeout=300):\n    \"\"\"Poll for async audio generation results.\"\"\"\n    start_time = time.time()\n\n    while time.time() - start_time < timeout:\n        fetch = requests.post(\n            f\"https://modelslab.com/api/v7/voice/fetch/{request_id}\",\n            json={\"key\": api_key}\n        )\n        result = fetch.json()\n\n        if result[\"status\"] == \"success\":\n            return result[\"output\"][0]\n        elif result[\"status\"] == \"failed\":\n            raise Exception(result.get(\"message\", \"Generation failed\"))\n\n        time.sleep(5)\n\n    raise Exception(\"Timeout waiting for audio generation\")\n```\n\n## Available ElevenLabs Voice IDs\n\n| Voice ID | Name | Style |\n|----------|------|-------|\n| `21m00Tcm4TlvDq8ikWAM` | Rachel | Neutral, calm |\n| `AZnzlk1XvdvUeBnXmlld` | Domi | Confident |\n| `EXAVITQu4vr4xnSDxMaL` | Bella | Soft, warm |\n| `ErXwobaYiN019PkySvjV` | Antoni | Well-rounded |\n| `MF3mGyEYCl7XYWbV9V6O` | Elli | Young, clear |\n| `TxGEqnHWrfWFTfGW9XjX` | Josh | Deep, warm |\n| `VR6AewLTigWG4xSOukaG` | Arnold | Strong |\n| `pNInz6obpgDQGcFmaJgB` | Adam | Deep, narrative |\n| `yoZ06aMxZJJ28mfd3POQ` | Sam | Dynamic |\n\n## Key Parameters\n\n### Text to Speech\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `prompt` | string | Yes | Text to convert to speech |\n| `voice_id` | string | Yes | ElevenLabs voice identifier |\n| `model_id` | string | Yes | TTS model (e.g., `eleven_multilingual_v2`) |\n| `temperature` | float | No | Voice variation |\n| `webhook` | string | No | Async notification URL |\n\n### Speech to Text\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `init_audio` | string | Yes | URL of audio to transcribe |\n| `model_id` | string | Yes | STT model (e.g., `scribe_v1`) |\n\n### Sound Generation\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `prompt` | string | Yes | Sound effect description |\n| `model_id` | string | Yes | SFX model (e.g., `eleven_sound_effect`) |\n\n## v6 to v7 Parameter Changes\n\n| v6 Parameter | v7 Parameter | Notes |\n|-------------|-------------|-------|\n| `text` | `prompt` | TTS text input |\n| `audio` | `init_audio` | STT/STS audio input |\n| `target_audio` | `init_audio` | Voice-to-voice source |\n| (not required) | `model_id` | Now required on all endpoints |\n\n## Best Practices\n\n### 1. Use Correct Voice IDs\nTTS requires valid ElevenLabs voice IDs (not generic names like \"alloy\").\n\n### 2. Ensure Audio Accessibility\nAudio URLs for speech-to-text must be publicly accessible without redirects or authentication.\n\n### 3. Use Webhooks for Long Operations\n```python\npayload = {\n    \"key\": api_key,\n    \"prompt\": \"...\",\n    \"model_id\": \"eleven_multilingual_v2\",\n    \"webhook\": \"https://yourserver.com/webhook/audio\",\n    \"track_id\": \"audio_001\"\n}\n```\n\n## Error Handling\n\n```python\ntry:\n    audio = text_to_speech(text, api_key)\n    print(f\"Audio generated: {audio}\")\nexcept Exception as e:\n    print(f\"Audio generation failed: {e}\")\n```\n\n## Resources\n\n- **Audio API Docs**: https://docs.modelslab.com/voice-cloning/overview\n- **Model Browser**: https://modelslab.com/models\n- **Model Selection Guide**: https://docs.modelslab.com/guides/model-selection\n- **Get API Key**: https://modelslab.com/dashboard\n\n## Related Skills\n\n- `modelslab-model-discovery` - Find and filter models\n- `modelslab-video-generation` - Add audio to videos\n- `modelslab-chat-generation` - Chat with LLM models\n- `modelslab-webhooks` - Handle async audio generation\n\nFile v1.0.0:billing-subscriptions/SKILL.md\n\n---\nname: modelslab-billing-subscriptions\ndescription: Manage ModelsLab billing, wallet balance, payment methods, subscriptions, invoices, and coupons programmatically via the Agent Control Plane API.\n---\n\n# ModelsLab Billing & Subscriptions\n\nManage billing, wallet funding, payment methods, subscriptions, and coupons via the Agent Control Plane API.\n\n## When to Use This Skill\n\n- Check wallet balance and fund it\n- Set up auto-recharge for wallets\n- Manage payment methods (add, set default, remove)\n- Create payment links for human-assisted checkout\n- Confirm Stripe Checkout sessions (wallet funding or subscriptions)\n- View and download invoices\n- Create, upgrade, pause, or resume subscriptions\n- Validate and redeem coupons\n- Update billing information (address, tax ID)\n\n## Authentication\n\nAll billing endpoints require a bearer token.\n\n```\nBase URL: https://modelslab.com/api/agents/v1\nAuthorization: Bearer <agent_access_token>\n```\n\nGet a token via the `modelslab-account-management` skill or `POST /auth/login`.\n\n## Helper\n\n```python\nimport requests\n\nBASE = \"https://modelslab.com/api/agents/v1\"\n\ndef headers(token):\n    return {\"Authorization\": f\"Bearer {token}\"}\n```\n\n## Billing Overview\n\n```python\ndef get_billing_overview(token):\n    \"\"\"Get billing overview — balance, active subscriptions, recent charges.\"\"\"\n    resp = requests.get(f\"{BASE}/billing/overview\", headers=headers(token))\n    return resp.json()[\"data\"]\n\n# Usage\noverview = get_billing_overview(token)\nprint(f\"Wallet balance: ${overview.get('wallet_balance', 0)}\")\n```\n\n## Three Payment Paths\n\nModelsLab supports three ways for agents to handle payments:\n\n| Path | Best For | Flow |\n|------|----------|------|\n| **Headless** | Autonomous agents with card data | `GET /billing/stripe-config` -> tokenize via Stripe API -> pass `payment_method_id` to fund/subscribe |\n| **Setup Intent** | Save a card for reuse without immediate charge | `POST /billing/setup-intent` -> confirm with Stripe -> reuse `payment_method_id` for future fund/subscribe |\n| **Human-Assisted** | Agents that cannot handle card data directly | `POST /billing/payment-link` -> forward URL to human -> human pays on Stripe Checkout -> poll `confirm-checkout` |\n\n## Stripe Config\n\nFetch the Stripe publishable key dynamically instead of hardcoding it. Useful for agents that need to tokenize cards client-side.\n\n```python\ndef get_stripe_config(token):\n    \"\"\"Get the Stripe publishable key for client-side card tokenization.\n\n    Returns:\n        publishable_key: Stripe publishable key (pk_...)\n        instructions: Usage guidance from the API\n    \"\"\"\n    resp = requests.get(f\"{BASE}/billing/stripe-config\", headers=headers(token))\n    return resp.json()[\"data\"]\n\n# Usage\nconfig = get_stripe_config(token)\nstripe_pk = config[\"publishable_key\"]  # e.g., \"pk_live_...\"\n```\n\n> **Tip:** The publishable key is safe to embed in agent code — it can only create tokens, never charge directly. You can either fetch it dynamically via this endpoint or use the hardcoded key below.\n\n## Headless Card Tokenization (Recommended)\n\nAgents create PaymentMethods directly via the Stripe API using the ModelsLab publishable key. Card data goes to Stripe only — ModelsLab never sees raw card numbers.\n\nFetch the Stripe publishable key dynamically via `GET /billing/stripe-config`. This ensures your agent always uses the current key without redeploying when it rotates.\n\n```python\nimport requests\n\n# Fetch publishable key from API\nconfig_resp = requests.get(\n    f\"{BASE}/billing/stripe-config\",\n    headers={\"Authorization\": f\"Bearer {TOKEN}\"}\n)\nSTRIPE_PK = config_resp.json()[\"publishable_key\"]\n\ndef create_payment_method(card_number, exp_month, exp_year, cvc):\n    \"\"\"Create a Stripe PaymentMethod directly — card data never touches ModelsLab.\n\n    Args:\n        card_number: Card number (e.g., \"4242424242424242\")\n        exp_month: Expiry month (e.g., 12)\n        exp_year: Expiry year (e.g., 2027)\n        cvc: CVC code (e.g., \"123\")\n\n    Returns:\n        Stripe PaymentMethod ID (pm_...) for use with ModelsLab endpoints.\n    \"\"\"\n    resp = requests.post(\n        \"https://api.stripe.com/v1/payment_methods\",\n        auth=(STRIPE_PK, \"\"),\n        data={\n            \"type\": \"card\",\n            \"card[number]\": card_number,\n            \"card[exp_month]\": exp_month,\n            \"card[exp_year]\": exp_year,\n            \"card[cvc]\": cvc,\n        }\n    )\n    return resp.json()[\"id\"]  # e.g., \"pm_1Xyz...\"\n\n# Usage — complete headless payment flow:\npm_id = create_payment_method(\"4242424242424242\", 12, 2027, \"123\")\nfund_wallet(token, 25, payment_method_id=pm_id)  # or create_subscription(...)\n```\n\n## Setup Intent Flow\n\nUse a SetupIntent to save a card for future use without an immediate charge. The confirmed PaymentMethod can then be reused for wallet funding or subscriptions.\n\n```python\ndef create_setup_intent(token):\n    \"\"\"Create a Stripe SetupIntent to save a card for future use.\n\n    Returns:\n        client_secret: Use with Stripe.js or Stripe API to confirm the SetupIntent\n        setup_intent_id: The SetupIntent ID (seti_...)\n    \"\"\"\n    resp = requests.post(f\"{BASE}/billing/setup-intent\", headers=headers(token))\n    return resp.json()[\"data\"]\n\n# Usage — save a card for reuse\nsetup = create_setup_intent(token)\nclient_secret = setup[\"client_secret\"]\n\n# Confirm the SetupIntent via Stripe API with card details\nstripe_pk = get_stripe_config(token)[\"publishable_key\"]\nconfirm_resp = requests.post(\n    f\"https://api.stripe.com/v1/setup_intents/{setup['setup_intent_id']}/confirm\",\n    auth=(stripe_pk, \"\"),\n    data={\n        \"payment_method_data[type]\": \"card\",\n        \"payment_method_data[card][number]\": \"4242424242424242\",\n        \"payment_method_data[card][exp_month]\": 12,\n        \"payment_method_data[card][exp_year]\": 2027,\n        \"payment_method_data[card][cvc]\": \"123\",\n    }\n)\npm_id = confirm_resp.json()[\"payment_method\"]  # e.g., \"pm_...\"\n\n# Now attach and reuse the payment method\nadd_payment_method(token, pm_id, make_default=True)\nfund_wallet(token, 50, payment_method_id=pm_id)\n```\n\n## Human-Assisted Payment (Payment Links)\n\nFor agents that cannot handle card data directly (e.g., chatbots, voice assistants), create a Stripe-hosted payment URL and forward it to a human user. ModelsLab controls the `success_url` — agents cannot override it.\n\n```python\ndef create_payment_link(token, purpose, amount=None, plan_id=None):\n    \"\"\"Create a Stripe-hosted payment URL for a human to complete.\n\n    Args:\n        purpose: \"fund\" for wallet funding, \"subscribe\" for subscription\n        amount: Required if purpose is \"fund\" — amount in USD (min $10)\n        plan_id: Required if purpose is \"subscribe\" — plan ID from list_plans()\n\n    Returns:\n        payment_url: Stripe Checkout URL to forward to the human\n        session_id: Checkout session ID (cs_...) for confirming later\n        purpose: Echoed back\n        amount: Echoed back (for fund)\n        expires_at: When the payment link expires\n        instructions: Guidance for the agent\n\n    Note:\n        success_url is NOT accepted — ModelsLab controls redirects.\n        After payment, the human sees ModelsLab's success page with the session_id\n        to copy back to the agent.\n    \"\"\"\n    payload = {\"purpose\": purpose}\n    if amount is not None:\n        payload[\"amount\"] = amount\n    if plan_id is not None:\n        payload[\"plan_id\"] = plan_id\n\n    resp = requests.post(\n        f\"{BASE}/billing/payment-link\",\n        headers=headers(token),\n        json=payload\n    )\n    return resp.json()[\"data\"]\n\n# Usage — wallet funding via human\nlink = create_payment_link(token, purpose=\"fund\", amount=50)\nprint(f\"Please complete payment at: {link['payment_url']}\")\nprint(f\"Session ID: {link['session_id']} (expires {link['expires_at']})\")\n\n# Usage — subscription via human\nplans = list_plans(token)\nchosen_plan = plans[\"subscription_plans\"][0]\nlink = create_payment_link(token, purpose=\"subscribe\", plan_id=chosen_plan[\"id\"])\nprint(f\"Please subscribe at: {link['payment_url']}\")\n```\n\n### Confirming Checkout Sessions\n\nAfter the human completes payment on the Stripe Checkout page, confirm the session to finalize the transaction. Use the `session_id` from `create_payment_link()` or from the human after they see the success page.\n\n```python\ndef confirm_wallet_checkout(token, session_id):\n    \"\"\"Confirm a Stripe Checkout session for wallet funding.\n\n    Call this after the human completes payment on the Stripe Checkout page.\n\n    Args:\n        session_id: The Checkout session ID (cs_...) from create_payment_link()\n    \"\"\"\n    resp = requests.post(\n        f\"{BASE}/wallet/confirm-checkout\",\n        headers=headers(token),\n        json={\"session_id\": session_id}\n    )\n    return resp.json()[\"data\"]\n\ndef confirm_subscription_checkout(token, session_id):\n    \"\"\"Confirm a Stripe Checkout session for subscription.\n\n    Call this after the human completes payment on the Stripe Checkout page.\n\n    Args:\n        session_id: The Checkout session ID (cs_...) from create_payment_link()\n    \"\"\"\n    resp = requests.post(\n        f\"{BASE}/subscriptions/confirm-checkout\",\n        headers=headers(token),\n        json={\"session_id\": session_id}\n    )\n    return resp.json()[\"data\"]\n\n# Usage — complete human-assisted wallet funding flow\nlink = create_payment_link(token, purpose=\"fund\", amount=50)\nprint(f\"Pay here: {link['payment_url']}\")\n# ... human pays ...\nsession_id = link[\"session_id\"]  # or human copies it from success page\nresult = confirm_wallet_checkout(token, session_id)\nprint(f\"Wallet funded! New balance: ${result.get('balance')}\")\n\n# Usage — complete human-assisted subscription flow\nlink = create_payment_link(token, purpose=\"subscribe\", plan_id=42)\nprint(f\"Subscribe here: {link['payment_url']}\")\n# ... human pays ...\nresult = confirm_subscription_checkout(token, link[\"session_id\"])\nprint(f\"Subscription active! Status: {result.get('status')}\")\n```\n\n## Payment Methods\n\n### List Payment Methods\n\n```python\ndef list_payment_methods(token):\n    \"\"\"List all saved payment methods.\"\"\"\n    resp = requests.get(f\"{BASE}/billing/payment-methods\", headers=headers(token))\n    return resp.json()[\"data\"]\n```\n\n### Add Payment Method\n\n```python\ndef add_payment_method(token, payment_method_id, make_default=True):\n    \"\"\"Add a Stripe payment method.\n\n    Args:\n        payment_method_id: Stripe PaymentMethod ID (pm_...)\n        make_default: Set as default payment method\n    \"\"\"\n    resp = requests.post(\n        f\"{BASE}/billing/payment-methods\",\n        headers=headers(token),\n        json={\n            \"payment_method_id\": payment_method_id,\n            \"make_default\": make_default\n        }\n    )\n    return resp.json()[\"data\"]\n```\n\n### Set Default & Remove\n\n```python\ndef set_default_payment_method(token, payment_method_id):\n    \"\"\"Set a payment method as the default.\"\"\"\n    requests.put(\n        f\"{BASE}/billing/payment-methods/{payment_method_id}/default\",\n        headers=headers(token)\n    )\n\ndef remove_payment_method(token, payment_method_id):\n    \"\"\"Remove a payment method.\"\"\"\n    requests.delete(\n        f\"{BASE}/billing/payment-methods/{payment_method_id}\",\n        headers=headers(token)\n    )\n```\n\n## Billing Info\n\n```python\ndef get_billing_info(token):\n    \"\"\"Get billing name, address, and tax ID.\"\"\"\n    resp = requests.get(f\"{BASE}/billing/info\", headers=headers(token))\n    return resp.json()[\"data\"]\n\ndef update_billing_info(token, **kwargs):\n    \"\"\"Update billing information.\n\n    Kwargs: name, email, tax_id, tax_id_type,\n            address_line1, address_line2, address_city,\n            address_state, address_postal_code, address_country\n    \"\"\"\n    resp = requests.put(\n        f\"{BASE}/billing/info\",\n        headers=headers(token),\n        json=kwargs\n    )\n    return resp.json()[\"data\"]\n\n# Usage\nupdate_billing_info(\n    token,\n    name=\"Acme Corp\",\n    email=\"billing@acme.com\",\n    tax_id=\"EU123456789\",\n    tax_id_type=\"eu_vat\",\n    address_line1=\"123 AI Street\",\n    address_city=\"San Francisco\",\n    address_state=\"CA\",\n    address_postal_code=\"94105\",\n    address_country=\"US\"\n)\n```\n\n## Invoices\n\n```python\ndef list_invoices(token):\n    \"\"\"List all invoices.\"\"\"\n    resp = requests.get(f\"{BASE}/billing/invoices\", headers=headers(token))\n    return resp.json()[\"data\"]\n\ndef get_invoice(token, invoice_id):\n    \"\"\"Get invoice details.\"\"\"\n    resp = requests.get(\n        f\"{BASE}/billing/invoices/{invoice_id}\",\n        headers=headers(token)\n    )\n    return resp.json()[\"data\"]\n\ndef get_invoice_pdf(token, invoice_id):\n    \"\"\"Get invoice PDF download URL.\"\"\"\n    resp = requests.get(\n        f\"{BASE}/billing/invoices/{invoice_id}/pdf\",\n        headers=headers(token)\n    )\n    return resp.json()[\"data\"]\n```\n\n## Wallet\n\n### Wallet Balance\n\n```python\ndef get_wallet_balance(token):\n    \"\"\"Quick wallet balance check.\"\"\"\n    resp = requests.get(f\"{BASE}/wallet/balance\", headers=headers(token))\n    return resp.json()[\"data\"]\n\n# Usage\nbalance = get_wallet_balance(token)\nprint(f\"Balance: ${balance['balance']} {balance['currency']}\")\n```\n\n### Wallet Transactions\n\n```python\ndef get_wallet_transactions(token, type=None, limit=50, offset=0):\n    \"\"\"Get wallet transaction ledger (deposits, charges, refunds).\n\n    Args:\n        type: Filter by \"credit\" or \"debit\" (optional)\n        limit: Max items 1-200 (default 50)\n        offset: Pagination offset (default 0)\n    \"\"\"\n    params = {\"limit\": limit, \"offset\": offset}\n    if type: params[\"type\"] = type\n\n    resp = requests.get(\n        f\"{BASE}/wallet/transactions\",\n        headers=headers(token),\n        params=params\n    )\n    return resp.json()[\"data\"]\n\n# Usage\ntxns = get_wallet_transactions(token, type=\"debit\", limit=20)\nfor txn in txns[\"items\"]:\n    print(f\"{txn['created_at']}: {txn['type']} ${txn['amount']} — {txn['usecase']}\")\nprint(f\"Wallet balance: ${txns['wallet']['balance']}\")\n```\n\n### Fund Wallet\n\n```python\ndef fund_wallet(token, amount, payment_method_id=None, idempotency_key=None):\n    \"\"\"Add funds to wallet.\n\n    Args:\n        amount: Amount in USD (min $10)\n        payment_method_id: Stripe PM ID from create_payment_method() (recommended)\n        idempotency_key: Prevent duplicate charges on retries (optional)\n    \"\"\"\n    payload = {\"amount\": amount}\n    if payment_method_id:\n        payload[\"payment_method_id\"] = payment_method_id\n\n    h = headers(token)\n    if idempotency_key:\n        h[\"Idempotency-Key\"] = idempotency_key\n\n    resp = requests.post(f\"{BASE}/wallet/fund\", headers=h, json=payload)\n    return resp.json()[\"data\"]\n\n# Usage — headless payment flow\npm_id = create_payment_method(\"4242424242424242\", 12, 2027, \"123\")\nfund_wallet(token, 50, payment_method_id=pm_id, idempotency_key=\"fund-50-20260220\")\n```\n\n### Check Payment Status\n\n```python\ndef get_payment_status(token, payment_intent_id):\n    \"\"\"Check the status of a Stripe PaymentIntent.\"\"\"\n    resp = requests.get(\n        f\"{BASE}/payments/{payment_intent_id}/status\",\n        headers=headers(token)\n    )\n    return resp.json()[\"data\"]\n\n# Usage\nstatus = get_payment_status(token, \"pi_xxx\")\nprint(f\"Payment status: {status['status']}\")\n```\n\n### Auto-Recharge\n\n```python\ndef enable_auto_funding(token, auto_charge_amount, charge_threshold):\n    \"\"\"Enable automatic wallet recharge.\n\n    Args:\n        auto_charge_amount: Amount to charge (min $5)\n        charge_threshold: Balance threshold to trigger charge (min $1)\n    \"\"\"\n    resp = requests.put(\n        f\"{BASE}/wallet/auto-funding\",\n        headers=headers(token),\n        json={\n            \"auto_charge_amount\": auto_charge_amount,\n            \"charge_threshold\": charge_threshold\n        }\n    )\n    return resp.json()[\"data\"]\n\ndef disable_auto_funding(token):\n    \"\"\"Disable automatic wallet recharge.\"\"\"\n    requests.delete(f\"{BASE}/wallet/auto-funding\", headers=headers(token))\n\n# Usage — auto-charge $25 when balance drops below $5\nenable_auto_funding(token, auto_charge_amount=25, charge_threshold=5)\n```\n\n### Withdraw\n\n```python\ndef withdraw(token, amount):\n    \"\"\"Withdraw from wallet balance.\"\"\"\n    resp = requests.post(\n        f\"{BASE}/wallet/withdraw\",\n        headers=headers(token),\n        json={\"amount\": amount}\n    )\n    return resp.json()[\"data\"]\n```\n\n### Coupons\n\n```python\ndef validate_coupon(token, coupon_code, purchase_amount=None):\n    \"\"\"Validate a coupon code before redeeming (GET request).\"\"\"\n    params = {\"coupon_code\": coupon_code}\n    if purchase_amount:\n        params[\"purchase_amount\"] = purchase_amount\n\n    resp = requests.get(\n        f\"{BASE}/wallet/coupons/validate\",\n        headers=headers(token),\n        params=params\n    )\n    return resp.json()[\"data\"]\n\ndef redeem_coupon(token, coupon_code, payment_method_id=None, purchase_amount=None):\n    \"\"\"Redeem a coupon code.\"\"\"\n    payload = {\"coupon_code\": coupon_code}\n    if payment_method_id:\n        payload[\"payment_method_id\"] = payment_method_id\n    if purchase_amount:\n        payload[\"purchase_amount\"] = purchase_amount\n\n    resp = requests.post(\n        f\"{BASE}/wallet/coupons/redeem\",\n        headers=headers(token),\n        json=payload\n    )\n    return resp.json()[\"data\"]\n\n# Usage\ninfo = validate_coupon(token, \"WELCOME50\")\nif not info.get(\"error\"):\n    redeem_coupon(token, \"WELCOME50\")\n```\n\n## Subscriptions\n\n### Discover Available Plans\n\nBefore creating a subscription, discover available plans and pay-as-you-go options:\n\n```python\ndef list_plans(token):\n    \"\"\"List all available subscription plans and pay-as-you-go options.\n\n    Returns:\n        subscription_plans: Array of plans with id, name, price, features\n        pay_as_you_go: Info about wallet-based billing (min $10 topup, auto-payments)\n    \"\"\"\n    resp = requests.get(f\"{BASE}/subscriptions/plans\", headers=headers(token))\n    return resp.json()[\"data\"]\n\n# Usage\nplans_data = list_plans(token)\n\n# Show subscription plans\nfor plan in plans_data[\"subscription_plans\"]:\n    print(f\"{plan['name']} - ${plan['price']}/{plan['period']} (ID: {plan['id']})\")\n    print(f\"  Features: {', '.join(plan['features'])}\")\n\n# Show pay-as-you-go option\npayg = plans_data[\"pay_as_you_go\"]\nif payg[\"available\"]:\n    print(f\"\\nPay-as-you-go: min ${payg['minimum_topup_usd']} topup\")\n    print(f\"Auto-payments: {payg['auto_payments']['supported']}\")\n```\n\n### List Subscriptions\n\n```python\ndef list_subscriptions(token):\n    \"\"\"List all active subscriptions.\"\"\"\n    resp = requests.get(f\"{BASE}/subscriptions\", headers=headers(token))\n    return resp.json()[\"data\"]\n```\n\n### Create Subscription\n\n```python\ndef create_subscription(token, plan_id, success_url=None):\n    \"\"\"Start a new subscription. Returns a Stripe checkout URL.\n\n    Use list_plans() first to discover valid plan IDs.\n\n    Args:\n        plan_id: The plan ID from list_plans() response\n        success_url: Redirect after successful checkout\n    \"\"\"\n    payload = {\"plan_id\": plan_id}\n    if success_url: payload[\"success_url\"] = success_url\n\n    resp = requests.post(\n        f\"{BASE}/subscriptions\",\n        headers=headers(token),\n        json=payload\n    )\n    return resp.json()[\"data\"]\n\n# Usage — discover plans, then subscribe\nplans = list_plans(token)\nchosen_plan = plans[\"subscription_plans\"][0]  # Pick a plan\nresult = create_subscription(token, chosen_plan[\"id\"])\nprint(f\"Checkout URL: {result['checkout_url']}\")\n```\n\n### Create Subscription (Headless — Recommended)\n\nSubscribe headlessly with a `payment_method_id` from the Stripe API. No Checkout redirect needed.\n\n```python\ndef create_subscription_headless(token, plan_id, payment_method_id, idempotency_key=None):\n    \"\"\"Create a subscription headlessly with a Stripe PaymentMethod.\n\n    No browser redirect — fully headless.\n    Use list_plans() first to discover valid plan IDs.\n    Use create_payment_method() to get a pm_id from Stripe.\n\n    Args:\n        plan_id: The plan ID from list_plans() response\n        payment_method_id: Stripe PM ID from create_payment_method()\n        idempotency_key: Prevent duplicate subscriptions on retries (optional)\n    \"\"\"\n    h = headers(token)\n    if idempotency_key:\n        h[\"Idempotency-Key\"] = idempotency_key\n\n    resp = requests.post(\n        f\"{BASE}/subscriptions\",\n        headers=h,\n        json={\n            \"plan_id\": plan_id,\n            \"payment_method_id\": payment_method_id\n        }\n    )\n    return resp.json()[\"data\"]\n\n# Usage — full headless flow\npm_id = create_payment_method(\"4242424242424242\", 12, 2027, \"123\")\nplans = list_plans(token)\nchosen_plan = plans[\"subscription_plans\"][0]\nresult = create_subscription_headless(token, chosen_plan[\"id\"], pm_id)\nprint(f\"Status: {result['status']}\")\n```\n\n### Check Subscription Status\n\n```python\ndef get_subscription_status(token, subscription_id):\n    \"\"\"Check the current status of a subscription.\"\"\"\n    resp = requests.get(\n        f\"{BASE}/subscriptions/{subscription_id}/status\",\n        headers=headers(token)\n    )\n    return resp.json()[\"data\"]\n```\n\n### Update (Upgrade/Downgrade)\n\n```python\ndef update_subscription(token, subscription_id, new_plan_id):\n    \"\"\"Change a subscription to a different plan.\"\"\"\n    resp = requests.put(\n        f\"{BASE}/subscriptions/{subscription_id}\",\n        headers=headers(token),\n        json={\"new_plan_id\": new_plan_id}\n    )\n    return resp.json()[\"data\"]\n```\n\n### Pause & Resume\n\n```python\ndef pause_subscription(token, subscription_id):\n    \"\"\"Pause a subscription.\"\"\"\n    resp = requests.post(\n        f\"{BASE}/subscriptions/{subscription_id}/pause\",\n        headers=headers(token)\n    )\n    return resp.json()[\"data\"]\n\ndef resume_subscription(token, subscription_id):\n    \"\"\"Resume a paused subscription.\"\"\"\n    resp = requests.post(\n        f\"{BASE}/subscriptions/{subscription_id}/resume\",\n        headers=headers(token)\n    )\n    return resp.json()[\"data\"]\n```\n\n### Other Subscription Actions\n\n```python\ndef reset_subscription_cycle(token, subscription_id):\n    \"\"\"Reset the current billing cycle.\"\"\"\n    requests.post(\n        f\"{BASE}/subscriptions/{subscription_id}/reset-cycle\",\n        headers=headers(token)\n    )\n\ndef charge_subscription_amount(token, amount):\n    \"\"\"Charge a custom amount ($5-$10,000).\"\"\"\n    resp = requests.post(\n        f\"{BASE}/subscriptions/charge-amount\",\n        headers=headers(token),\n        json={\"amount\": amount}\n    )\n    return resp.json()[\"data\"]\n\ndef fix_payment(token, subscription_id):\n    \"\"\"Fix a failed subscription payment.\"\"\"\n    requests.post(\n        f\"{BASE}/subscriptions/{subscription_id}/fix-payment\",\n        headers=headers(token)\n    )\n```\n\n## Common Workflow: Ensure Funded Account\n\n```python\ndef ensure_account_funded(token, min_balance=10, top_up_amount=50):\n    \"\"\"Check wallet balance and fund if low.\"\"\"\n    overview = get_billing_overview(token)\n    balance = overview.get(\"wallet_balance\", 0)\n\n    if balance < min_balance:\n        print(f\"Balance ${balance} below ${min_balance}, funding ${top_up_amount}...\")\n        fund_wallet(token, top_up_amount)\n        print(\"Wallet funded!\")\n    else:\n        print(f\"Balance OK: ${balance}\")\n\n# Usage\nensure_account_funded(token, min_balance=5, top_up_amount=25)\n```\n\n## Common Workflow: Human-Assisted Funding with Polling\n\n```python\nimport time\n\ndef fund_via_human(token, amount, poll_interval=5, max_wait=300):\n    \"\"\"Create a payment link and poll until the human completes it.\n\n    Args:\n        amount: Amount in USD\n        poll_interval: Seconds between balance checks\n        max_wait: Maximum seconds to wait before giving up\n    \"\"\"\n    # Get initial balance\n    initial = get_wallet_balance(token)[\"balance\"]\n\n    # Create payment link\n    link = create_payment_link(token, purpose=\"fund\", amount=amount)\n    print(f\"Please fund your wallet at: {link['payment_url']}\")\n    print(f\"Waiting for payment (expires {link['expires_at']})...\")\n\n    # Poll for confirmation\n    elapsed = 0\n    while elapsed < max_wait:\n        time.sleep(poll_interval)\n        elapsed += poll_interval\n        try:\n            result = confirm_wallet_checkout(token, link[\"session_id\"])\n            print(f\"Payment confirmed! New balance: ${result.get('balance')}\")\n            return result\n        except Exception:\n            # Session not yet completed, keep polling\n            pass\n\n    print(\"Payment not completed within timeout.\")\n    return None\n\n# Usage\nfund_via_human(token, amount=50, max_wait=600)\n```\n\n## MCP Server Access\n\nThese same capabilities are available via the Agent Control Plane MCP server:\n- **URL**: `https://modelslab.com/mcp/agents`\n- **Tools**: `agent-billing`, `agent-wallet`, `agent-subscriptions` (use `list-plans` action to discover plans)\n\nSee: https://docs.modelslab.com/mcp-web-api/agent-control-plane\n\n## API Endpoints Reference\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| GET | `/billing/overview` | Billing overview |\n| GET | `/billing/stripe-config` | Get Stripe publishable key |\n| POST | `/billing/setup-intent` | Create SetupIntent for card saving |\n| POST | `/billing/payment-link` | Create Stripe Checkout payment URL |\n| GET | `/billing/payment-methods` | List payment methods |\n| POST | `/billing/payment-methods` | Add payment method |\n| PUT | `/billing/payment-methods/{id}/default` | Set default |\n| DELETE | `/billing/payment-methods/{id}` | Remove payment method |\n| GET | `/billing/info` | Get billing info |\n| PUT | `/billing/info` | Update billing info |\n| GET | `/billing/invoices` | List invoices |\n| GET | `/billing/invoices/{id}` | Invoice details |\n| GET | `/billing/invoices/{id}/pdf` | Invoice PDF URL |\n| GET | `/wallet/balance` | Quick wallet balance check |\n| GET | `/wallet/transactions` | Wallet transaction ledger |\n| POST | `/wallet/fund` | Fund wallet (with payment_method_id) |\n| POST | `/wallet/confirm-checkout` | Confirm Checkout wallet funding |\n| PUT | `/wallet/auto-funding` | Enable auto-recharge |\n| DELETE | `/wallet/auto-funding` | Disable auto-recharge |\n| POST | `/wallet/withdraw` | Withdraw balance |\n| GET | `/wallet/coupons/validate` | Validate coupon |\n| POST | `/wallet/coupons/redeem` | Redeem coupon |\n| GET | `/payments/{id}/status` | Check payment intent status |\n| GET | `/subscriptions/plans` | List available plans + pay-as-you-go |\n| GET | `/subscriptions` | List subscriptions (addon, enterprise, normal) |\n| POST | `/subscriptions` | Create subscription (headless with pm_id, or Checkout) |\n| POST | `/subscriptions/confirm-checkout` | Confirm Checkout subscription |\n| GET | `/subscriptions/{id}/status` | Check subscription status |\n| PUT | `/subscriptions/{id}` | Update subscription |\n| POST | `/subscriptions/{id}/pause` | Pause |\n| POST | `/subscriptions/{id}/resume` | Resume |\n| POST | `/subscriptions/{id}/reset-cycle` | Reset cycle |\n| POST | `/subscriptions/charge-amount` | Charge amount |\n| POST | `/subscriptions/{id}/fix-payment` | Fix payment |\n\n## Best Practices\n\n### 1. Choose the Right Payment Path\n```python\n# Headless — agent has card data, fully autonomous\npm_id = create_payment_method(\"4242424242424242\", 12, 2027, \"123\")\nfund_wallet(token, 50, payment_method_id=pm_id)\n\n# Setup Intent — save card first, charge later\nsetup = create_setup_intent(token)\n# ... confirm with Stripe API ...\nadd_payment_method(token, pm_id, make_default=True)\n\n# Human-Assisted — agent cannot handle cards\nlink = create_payment_link(token, purpose=\"fund\", amount=50)\n# Forward link['payment_url'] to human, then confirm_wallet_checkout()\n```\n\n### 2. Use Idempotency Keys for Billing\n```python\n# Prevent duplicate charges on retries\nfund_wallet(token, 50, payment_method_id=pm_id, idempotency_key=\"fund-50-unique-key\")\n```\n\n### 3. Set Up Auto-Recharge\n```python\n# Avoid running out of credits during generation\nenable_auto_funding(token, auto_charge_amount=25, charge_threshold=5)\n```\n\n### 4. Check Balance Before Large Jobs\n```python\nbalance = get_wallet_balance(token)\nif balance[\"balance\"] < estimated_cost:\n    fund_wallet(token, estimated_cost * 1.2)  # 20% buffer\n```\n\n### 5. Validate Coupons Before Redeeming\n```python\ninfo = validate_coupon(token, code)\n# Check discount amount, expiry, etc. before committing\n```\n\n### 6. Handle Card Failures Gracefully\n```python\nresult = fund_wallet(token, 50, payment_method_id=pm_id)\n# Check for errors\nif result.get(\"error\"):\n    if result[\"error\"][\"code\"] == \"payment_declined\":\n        print(f\"Card declined: {result['error']['details']['decline_code']}\")\n    # Try a different card or ask user\n```\n\n## Resources\n\n- **API Documentation**: https://docs.modelslab.com/agents-api/billing-and-wallet\n- **MCP Server**: https://docs.modelslab.com/mcp-web-api/agent-control-plane\n- **Pricing**: https://modelslab.com/pricing\n- **Dashboard**: https://modelslab.com/dashboard\n\n## Related Skills\n\n- `modelslab-account-management` - Account setup and API keys\n- `modelslab-model-discovery` - Check usage and find models\n- `modelslab-webhooks` - Per-request webhook URLs for async results\n\nFile v1.0.0:chat-generation/SKILL.md\n\n---\nname: modelslab-chat-generation\ndescription: Chat with LLM models using ModelsLab's OpenAI-compatible Chat Completions API. Supports 60+ models including DeepSeek R1, Meta Llama, Google Gemini, Qwen, and Mistral with streaming, function calling, and structured outputs.\n---\n\n# ModelsLab Chat/LLM Generation\n\nSend chat completions to 60+ LLM models through a single OpenAI-compatible endpoint.\n\n## When to Use This Skill\n\n- Chat with AI models (DeepSeek, Llama, Gemini, Qwen, Mistral)\n- Build conversational AI applications\n- Generate text completions with system prompts\n- Use function/tool calling with LLMs\n- Stream responses for real-time output\n- Get structured JSON responses\n\n## API Endpoint\n\n**Chat Completions**: `POST https://modelslab.com/api/v7/llm/chat/completions`\n\nThe endpoint follows the OpenAI chat completions format, making it easy to switch from OpenAI or use the OpenAI SDK.\n\n## Quick Start\n\n```python\nimport requests\n\ndef chat(message, api_key, model=\"meta-llama-3-8B-instruct\"):\n    \"\"\"Send a chat completion request.\n\n    Args:\n        message: The user message\n        api_key: Your ModelsLab API key\n        model: LLM model ID (use modelslab models search --feature llmaster to find models)\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v7/llm/chat/completions\",\n        json={\n            \"key\": api_key,\n            \"model_id\": model,\n            \"messages\": [\n                {\"role\": \"user\", \"content\": message}\n            ],\n            \"max_tokens\": 200,\n            \"temperature\": 0.7\n        }\n    )\n\n    data = response.json()\n\n    if \"choices\" in data:\n        return data[\"choices\"][0][\"message\"][\"content\"]\n    else:\n        raise Exception(f\"Error: {data.get('message', 'Unknown error')}\")\n\n# Usage\nreply = chat(\n    \"Explain quantum computing in simple terms.\",\n    \"your_api_key\"\n)\nprint(reply)\n```\n\n## With System Prompt\n\n```python\ndef chat_with_system(system_prompt, message, api_key, model=\"meta-llama-3-8B-instruct\"):\n    \"\"\"Chat with a system prompt for role/behavior control.\"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v7/llm/chat/completions\",\n        json={\n            \"key\": api_key,\n            \"model_id\": model,\n            \"messages\": [\n                {\"role\": \"system\", \"content\": system_prompt},\n                {\"role\": \"user\", \"content\": message}\n            ],\n            \"max_tokens\": 500,\n            \"temperature\": 0.7\n        }\n    )\n\n    data = response.json()\n    if \"choices\" in data:\n        return data[\"choices\"][0][\"message\"][\"content\"]\n\n# Usage\nreply = chat_with_system(\n    \"You are a Python expert. Give concise code examples.\",\n    \"How do I read a CSV file?\",\n    \"your_api_key\"\n)\n```\n\n## Multi-Turn Conversation\n\n```python\ndef conversation(messages, api_key, model=\"meta-llama-3-8B-instruct\"):\n    \"\"\"Send a multi-turn conversation.\"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v7/llm/chat/completions\",\n        json={\n            \"key\": api_key,\n            \"model_id\": model,\n            \"messages\": messages,\n            \"max_tokens\": 500,\n            \"temperature\": 0.7\n        }\n    )\n    return response.json()\n\n# Multi-turn example\nmessages = [\n    {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n    {\"role\": \"user\", \"content\": \"What is Python?\"},\n    {\"role\": \"assistant\", \"content\": \"Python is a high-level programming language...\"},\n    {\"role\": \"user\", \"content\": \"Show me a hello world example.\"}\n]\n\nresult = conversation(messages, \"your_api_key\")\nprint(result[\"choices\"][0][\"message\"][\"content\"])\n```\n\n## OpenAI SDK Compatibility\n\nYou can use the official OpenAI Python SDK by changing the base URL and API key:\n\n```python\nfrom openai import OpenAI\n\nclient = OpenAI(\n    base_url=\"https://modelslab.com/api/v7/llm\",\n    api_key=\"your_modelslab_api_key\"\n)\n\nresponse = client.chat.completions.create(\n    model=\"meta-llama-3-8B-instruct\",\n    messages=[\n        {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n        {\"role\": \"user\", \"content\": \"Hello!\"}\n    ],\n    max_tokens=100,\n    temperature=0.7\n)\n\nprint(response.choices[0].message.content)\n```\n\n## cURL Example\n\n```bash\ncurl -X POST \"https://modelslab.com/api/v7/llm/chat/completions\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"key\": \"your_api_key\",\n    \"model_id\": \"meta-llama-3-8B-instruct\",\n    \"messages\": [\n      {\"role\": \"user\", \"content\": \"Say hello in one sentence.\"}\n    ],\n    \"max_tokens\": 50,\n    \"temperature\": 0.7\n  }'\n```\n\n## Discovering LLM Models\n\n```bash\n# Search all chat/LLM models\nmodelslab models search --feature llmaster\n\n# Search by provider\nmodelslab models search --search \"deepseek\"\nmodelslab models search --search \"llama\"\nmodelslab models search --search \"gemini\"\n\n# Get model details\nmodelslab models detail --id meta-llama-3-8B-instruct\n```\n\n## Popular LLM Model IDs\n\n### Meta Llama\n- `meta-llama-3-8B-instruct` — Llama 3 8B (fast, efficient)\n- `meta-llama-Llama-3.3-70B-Instruct-Turbo` — Llama 3.3 70B (powerful)\n- `meta-llama-Meta-Llama-3.1-405B-Instruct-Turbo` — Llama 3.1 405B (largest)\n\n### DeepSeek\n- `deepseek-ai-DeepSeek-R1-Distill-Llama-70B` — DeepSeek R1 (reasoning)\n- `deepseek-ai-DeepSeek-V3` — DeepSeek V3 (general purpose)\n\n### Google\n- `gemini-2.0-flash-001` — Gemini 2.0 Flash (fast)\n- `gemini-2.5-pro` — Gemini 2.5 Pro (capable)\n\n### Qwen\n- `Qwen-Qwen2.5-72B-Instruct-Turbo` — Qwen 2.5 72B\n- `Qwen-Qwen2.5-Coder-32B-Instruct` — Qwen 2.5 Coder\n\n### Mistral\n- `mistralai-Mixtral-8x7B-Instruct-v0.1` — Mixtral 8x7B\n- `mistralai-Mistral-Small-24B-Instruct-2501` — Mistral Small\n\n## Key Parameters\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `model_id` | string | Yes | LLM model identifier (alias: `model`) |\n| `messages` | array | Yes | Array of message objects with `role` and `content` |\n| `temperature` | float | No | Sampling temperature (0-2, default varies by model) |\n| `max_tokens` | integer | No | Maximum tokens to generate |\n| `top_p` | float | No | Nucleus sampling (0-1) |\n| `top_k` | integer | No | Top-k sampling |\n| `frequency_penalty` | float | No | Frequency penalty (-2 to 2) |\n| `presence_penalty` | float | No | Presence penalty (-2 to 2) |\n| `streaming` | boolean | No | Enable streaming responses (alias: `stream`) |\n| `n` | integer | No | Number of completions (1-10) |\n| `stop` | array | No | Stop sequences (max 4) |\n| `seed` | integer | No | Random seed for reproducibility |\n| `tools` | array | No | Function/tool definitions |\n| `tool_choice` | string | No | Tool selection strategy |\n| `response_format` | object | No | `{\"type\": \"json_object\"}` for JSON mode |\n\n## Response Format\n\nThe response follows the OpenAI chat completions format:\n\n```json\n{\n  \"id\": \"gen-...\",\n  \"model\": \"meta-llama-3-8B-instruct\",\n  \"object\": \"chat.completion\",\n  \"created\": 1771658583,\n  \"choices\": [\n    {\n      \"index\": 0,\n      \"finish_reason\": \"stop\",\n      \"message\": {\n        \"role\": \"assistant\",\n        \"content\": \"Hello! How can I help you today?\"\n      }\n    }\n  ],\n  \"usage\": {\n    \"prompt_tokens\": 17,\n    \"completion_tokens\": 10,\n    \"total_tokens\": 27\n  }\n}\n```\n\n## Error Handling\n\n```python\ndef safe_chat(message, api_key, model=\"meta-llama-3-8B-instruct\"):\n    \"\"\"Chat with error handling.\"\"\"\n    try:\n        response = requests.post(\n            \"https://modelslab.com/api/v7/llm/chat/completions\",\n            json={\n                \"key\": api_key,\n                \"model_id\": model,\n                \"messages\": [{\"role\": \"user\", \"content\": message}],\n                \"max_tokens\": 200\n            }\n        )\n        data = response.json()\n\n        if \"choices\" in data:\n            return data[\"choices\"][0][\"message\"][\"content\"]\n        elif data.get(\"status\") == \"error\":\n            raise Exception(data.get(\"message\", \"Unknown error\"))\n        else:\n            raise Exception(f\"Unexpected response: {data}\")\n\n    except requests.exceptions.RequestException as e:\n        raise Exception(f\"Network error: {e}\")\n\ntry:\n    reply = safe_chat(\"Hello!\", \"your_api_key\")\n    print(reply)\nexcept Exception as e:\n    print(f\"Chat failed: {e}\")\n```\n\n## Resources\n\n- **API Documentation**: https://docs.modelslab.com/uncensored-chat-api/overview\n- **Model Browser**: https://modelslab.com/models\n- **Get API Key**: https://modelslab.com/dashboard/api-keys\n- **CLI Tool**: https://github.com/ModelsLab/modelslab-cli\n\n## Related Skills\n\n- `modelslab-model-discovery` - Find and filter models\n- `modelslab-account-management` - Manage API keys and billing\n- `modelslab-image-generation` - Generate images from text\n\nFile v1.0.0:deepfake/SKILL.md\n\n---\nname: modelslab-deepfake\ndescription: Face swap and deepfake generation using ModelsLab's Deepfake API. Swap faces in images and videos with high-quality AI-powered face replacement technology.\n---\n\n# ModelsLab Deepfake & Face Swap\n\nSwap faces in images and videos using advanced AI-powered deepfake technology.\n\n## When to Use This Skill\n\n- Swap faces in photos\n- Replace faces in videos\n- Create personalized video content\n- Generate character variations\n- Build face swap applications\n- Create entertainment content\n\n## Available Endpoints\n\n### Image Face Swap\n- **Specific Face Swap**: `POST https://modelslab.com/api/v6/deepfake/specific_face_swap`\n- **Multiple Face Swap**: `POST https://modelslab.com/api/v6/deepfake/multiple_face_swap`\n\n### Video Face Swap\n- **Single Video Swap**: `POST https://modelslab.com/api/v6/deepfake/single_video_swap`\n- **Specific Video Swap**: `POST https://modelslab.com/api/v6/deepfake/specific_video_swap`\n\n## Specific Face Swap (Image)\n\n```python\nimport requests\n\ndef swap_face(target_image, face_to_use, api_key):\n    \"\"\"Swap a face in an image.\n\n    Args:\n        target_image: URL of the image containing face to replace\n        face_to_use: URL of the image with face to swap in\n        api_key: Your ModelsLab API key\n\n    Returns:\n        URL of the face-swapped image\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/deepfake/specific_face_swap\",\n        json={\n            \"key\": api_key,\n            \"init_image\": target_image,\n            \"target_image\": face_to_use\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n    else:\n        raise Exception(f\"Error: {data.get('message', 'Unknown error')}\")\n\n# Usage\nresult = swap_face(\n    \"https://example.com/target-photo.jpg\",  # Photo to modify\n    \"https://example.com/face-to-swap.jpg\",  # Face to insert\n    \"your_api_key\"\n)\nprint(f\"Face swapped image: {result}\")\n```\n\n## Multiple Face Swap (Image)\n\n```python\ndef swap_multiple_faces(image_with_faces, face_to_use, api_key):\n    \"\"\"Swap all faces in an image with the same face.\n\n    Args:\n        image_with_faces: URL of image with multiple faces\n        face_to_use: URL of face to swap in\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/deepfake/multiple_face_swap\",\n        json={\n            \"key\": api_key,\n            \"init_image\": image_with_faces,\n            \"target_image\": face_to_use\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n    else:\n        raise Exception(data.get(\"message\"))\n\n# Swap all faces in group photo\nresult = swap_multiple_faces(\n    \"https://example.com/group-photo.jpg\",\n    \"https://example.com/celebrity-face.jpg\",\n    \"your_api_key\"\n)\n```\n\n## Single Video Face Swap\n\n```python\nimport time\n\ndef swap_video_faces(video_url, face_image, api_key, output_format=\"mp4\"):\n    \"\"\"Swap all faces in a video.\n\n    Args:\n        video_url: URL of the video\n        face_image: URL of face to swap in\n        output_format: \"mp4\" or \"gif\"\n\n    Returns:\n        URL of the face-swapped video\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/deepfake/single_video_swap\",\n        json={\n            \"key\": api_key,\n            \"init_video\": video_url,\n            \"target_image\": face_image,\n            \"output_format\": output_format,\n            \"watermark\": False  # Set to True for watermark\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"error\":\n        raise Exception(f\"Error: {data['message']}\")\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n\n    # Video processing is async\n    request_id = data[\"id\"]\n    print(f\"Video processing... Request ID: {request_id}\")\n\n    return poll_deepfake_result(request_id, api_key)\n\ndef poll_deepfake_result(request_id, api_key, timeout=900):\n    \"\"\"Poll for video face swap results.\"\"\"\n    start_time = time.time()\n\n    while time.time() - start_time < timeout:\n        fetch = requests.post(\n            f\"https://modelslab.com/api/v6/deepfake/fetch/{request_id}\",\n            json={\"key\": api_key}\n        )\n        result = fetch.json()\n\n        if result[\"status\"] == \"success\":\n            return result[\"output\"][0]\n        elif result[\"status\"] == \"failed\":\n            raise Exception(result.get(\"message\", \"Failed\"))\n\n        print(f\"Processing... ({int(time.time() - start_time)}s)\")\n        time.sleep(10)\n\n    raise Exception(\"Timeout\")\n\n# Usage\nswapped_video = swap_video_faces(\n    \"https://example.com/video.mp4\",\n    \"https://example.com/face.jpg\",\n    \"your_api_key\"\n)\nprint(f\"Face-swapped video: {swapped_video}\")\n```\n\n## Specific Video Face Swap\n\n```python\ndef swap_specific_video_face(video_url, new_face, reference_face, api_key):\n    \"\"\"Swap a specific face in a video (when multiple faces present).\n\n    Args:\n        video_url: URL of the video\n        new_face: URL of the face to swap in\n        reference_face: URL of the specific face to replace\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/deepfake/specific_video_swap\",\n        json={\n            \"key\": api_key,\n            \"init_video\": video_url,\n            \"target_image\": new_face,\n            \"source_image\": reference_face,\n            \"output_format\": \"mp4\",\n            \"watermark\": False\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"processing\":\n        return poll_deepfake_result(data[\"id\"], api_key)\n    elif data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n    else:\n        raise Exception(data.get(\"message\"))\n\n# Swap only one person's face in multi-person video\nresult = swap_specific_video_face(\n    \"https://example.com/interview.mp4\",\n    \"https://example.com/new-face.jpg\",\n    \"https://example.com/face-to-replace.jpg\",\n    \"your_api_key\"\n)\n```\n\n## Using Webhooks\n\n```python\ndef deepfake_with_webhook(video_url, face_image, api_key, webhook_url, track_id):\n    \"\"\"Process video face swap with webhook notification.\"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/deepfake/single_video_swap\",\n        json={\n            \"key\": api_key,\n            \"init_video\": video_url,\n            \"target_image\": face_image,\n            \"output_format\": \"mp4\",\n            \"webhook\": webhook_url,\n            \"track_id\": track_id\n        }\n    )\n\n    data = response.json()\n    print(f\"Request submitted: {data['id']}\")\n    return data[\"id\"]\n\n# Usage\nrequest_id = deepfake_with_webhook(\n    \"https://example.com/video.mp4\",\n    \"https://example.com/face.jpg\",\n    \"your_api_key\",\n    \"https://yourserver.com/webhook/deepfake\",\n    \"video_001\"\n)\n```\n\n## Key Parameters\n\n| Parameter | Description | Values |\n|-----------|-------------|--------|\n| `init_image` | Target image to modify | Image URL |\n| `init_video` | Target video to modify | Video URL |\n| `target_image` | Face to swap in | Image URL with clear face |\n| `source_image` | Specific face to replace | Image URL (for specific swap) |\n| `output_format` | Video output format | `mp4` or `gif` |\n| `watermark` | Add watermark | `true` or `false` |\n| `webhook` | Async callback URL | Your server endpoint |\n| `track_id` | Request identifier | Unique tracking ID |\n\n## Best Practices\n\n### 1. Use High-Quality Face Images\n```\n✓ Good: Clear, well-lit frontal face photo\n✓ Good: High resolution (at least 512x512)\n✓ Good: Neutral expression works best\n\n✗ Avoid: Blurry or low-resolution images\n✗ Avoid: Extreme angles or profiles\n✗ Avoid: Heavy shadows or poor lighting\n```\n\n### 2. Video Face Swap Requirements\n- Clear, visible faces in the video\n- Good lighting conditions\n- Frontal or near-frontal angles work best\n- Shorter videos process faster\n\n### 3. Handle Async Operations\n```python\n# Video face swaps are ALWAYS async\nif data[\"status\"] == \"processing\":\n    result = poll_deepfake_result(data[\"id\"], api_key)\n```\n\n### 4. Set Appropriate Timeouts\n```python\n# Video processing takes time\npoll_deepfake_result(request_id, api_key, timeout=900)  # 15 minutes\n```\n\n### 5. Use Webhooks for Long Videos\n```python\n# Don't poll for long videos, use webhooks\ndeepfake_with_webhook(video_url, face, api_key, webhook_url, track_id)\n```\n\n## Common Use Cases\n\n### Profile Picture Generator\n\n```python\ndef create_profile_variations(base_photo, face_images, api_key):\n    \"\"\"Generate multiple profile picture variations.\"\"\"\n    variations = []\n\n    for i, face in enumerate(face_images):\n        result = swap_face(base_photo, face, api_key)\n        variations.append(result)\n        print(f\"Variation {i+1} created: {result}\")\n\n    return variations\n\n# Create variations\nprofiles = create_profile_variations(\n    \"https://example.com/professional-photo.jpg\",\n    [\n        \"https://example.com/style1-face.jpg\",\n        \"https://example.com/style2-face.jpg\",\n        \"https://example.com/style3-face.jpg\"\n    ],\n    api_key\n)\n```\n\n### Video Personalization\n\n```python\ndef personalize_video(template_video, user_face, api_key):\n    \"\"\"Create personalized video with user's face.\"\"\"\n    personalized = swap_video_faces(\n        template_video,\n        user_face,\n        api_key,\n        output_format=\"mp4\"\n    )\n    print(f\"Personalized video: {personalized}\")\n    return personalized\n\n# Create custom greeting video\ngreeting = personalize_video(\n    \"https://example.com/greeting-template.mp4\",\n    \"https://example.com/user-photo.jpg\",\n    api_key\n)\n```\n\n### Character Variations\n\n```python\ndef generate_character_variations(character_image, face_options, api_key):\n    \"\"\"Generate different character variations.\"\"\"\n    characters = []\n\n    for face in face_options:\n        char = swap_face(character_image, face, api_key)\n        characters.append(char)\n\n    return characters\n```\n\n### Group Photo Editing\n\n```python\n# Replace one person in group photo\nedited_group_photo = swap_specific_video_face(\n    \"https://example.com/group-video.mp4\",\n    \"https://example.com/replacement-face.jpg\",\n    \"https://example.com/person-to-replace.jpg\",\n    api_key\n)\n```\n\n## Error Handling\n\n```python\ntry:\n    result = swap_face(target, face, api_key)\n    print(f\"Face swap successful: {result}\")\nexcept Exception as e:\n    print(f\"Face swap failed: {e}\")\n    # Check image quality, try different images, or notify user\n```\n\n## Performance Tips\n\n1. **Use Webhooks**: For videos, always use webhooks\n2. **Optimize Face Images**: Use clear, high-quality faces\n3. **Batch Process**: Submit multiple requests together\n4. **Cache Results**: Store generated content\n5. **Monitor Processing Time**: Track and optimize\n\n## Ethical Considerations\n\n⚠️ **Important**: Use face swap technology responsibly\n- Obtain consent before using someone's face\n- Don't create misleading or harmful content\n- Follow local laws and regulations\n- Respect privacy and image rights\n- Add disclaimers when sharing deepfake content\n\n## Enterprise API\n\nFor dedicated resources:\n\n```python\n# Enterprise endpoints\nurl = \"https://modelslab.com/api/v1/enterprise/deepfake/specific_face_swap\"\nurl = \"https://modelslab.com/api/v1/enterprise/deepfake/single_video_swap\"\n```\n\n## Resources\n\n- **Deepfake API Docs**: https://docs.modelslab.com/deepfake-api/overview\n- **Face Swap Image**: https://docs.modelslab.com/deepfake-api/specific-face-swap\n- **Video Face Swap**: https://docs.modelslab.com/deepfake-api/single-video-swap\n- **Get API Key**: https://modelslab.com/dashboard\n\n## Related Skills\n\n- `modelslab-video-generation` - Generate videos\n- `modelslab-webhooks` - Handle async operations\n- `modelslab-sdk-usage` - Use official SDKs\n\nFile v1.0.0:image-editing/SKILL.md\n\n---\nname: modelslab-image-editing\ndescription: Edit and enhance images using ModelsLab's Image Editing API. Features background removal, super resolution upscaling, outpainting, object removal, and AI-powered editing tools.\n---\n\n# ModelsLab Image Editing\n\nProfessional image editing tools powered by AI including background removal, upscaling, outpainting, and object manipulation.\n\n## When to Use This Skill\n\n- Remove backgrounds from images\n- Upscale images (2x, 4x super resolution)\n- Extend images beyond their borders (outpainting)\n- Remove unwanted objects from images\n- Create professional product photos\n- Enhance image quality\n- Edit images with AI assistance\n\n## Available Endpoints\n\n### Background Removal\n`POST https://modelslab.com/api/v6/image_editing/removebg`\n\n### Super Resolution (Upscaling)\n`POST https://modelslab.com/api/v6/image_editing/super_resolution`\n\n### Outpainting\n`POST https://modelslab.com/api/v6/image_editing/outpainting`\n\n### Object Removal\n`POST https://modelslab.com/api/v6/image_editing/object_removal`\n\n### Mask Creator\n`POST https://modelslab.com/api/v6/image_editing/create_mask`\n\n### Qwen Image Edit (AI Editing)\n`POST https://modelslab.com/api/v6/image_editing/qwen_edit`\n\n## Background Removal\n\n```python\nimport requests\n\ndef remove_background(image_url, api_key):\n    \"\"\"Remove background from an image.\n\n    Args:\n        image_url: URL of the image\n        api_key: Your ModelsLab API key\n\n    Returns:\n        URL of image with transparent background\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/image_editing/removebg\",\n        json={\n            \"key\": api_key,\n            \"image\": image_url\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n    else:\n        raise Exception(f\"Error: {data.get('message', 'Unknown error')}\")\n\n# Usage\nresult = remove_background(\n    \"https://example.com/product-photo.jpg\",\n    \"your_api_key\"\n)\nprint(f\"Image without background: {result}\")\n```\n\n## Super Resolution (Upscaling)\n\n```python\ndef upscale_image(image_url, api_key, scale=4):\n    \"\"\"Upscale an image to higher resolution.\n\n    Args:\n        image_url: URL of the image to upscale\n        scale: Upscale factor (2 or 4)\n\n    Returns:\n        URL of upscaled high-resolution image\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/image_editing/super_resolution\",\n        json={\n            \"key\": api_key,\n            \"image\": image_url,\n            \"scale\": scale  # 2x or 4x\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n    else:\n        raise Exception(data.get(\"message\"))\n\n# Upscale to 4x resolution\nhd_image = upscale_image(\n    \"https://example.com/low-res.jpg\",\n    \"your_api_key\",\n    scale=4\n)\nprint(f\"HD image: {hd_image}\")\n```\n\n## Outpainting (Extend Images)\n\n```python\ndef extend_image(image_url, prompt, api_key, width=1024, height=768):\n    \"\"\"Extend an image beyond its original boundaries.\n\n    Args:\n        image_url: Original image URL\n        prompt: Description of how to extend the image\n        width: New width (larger than original)\n        height: New height (larger than original)\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/image_editing/outpainting\",\n        json={\n            \"key\": api_key,\n            \"image\": image_url,\n            \"prompt\": prompt,\n            \"width\": width,\n            \"height\": height,\n            \"num_inference_steps\": 30,\n            \"guidance_scale\": 7.5\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n    elif data[\"status\"] == \"processing\":\n        return poll_result(data[\"id\"], api_key)\n\n# Extend a landscape image\nextended = extend_image(\n    \"https://example.com/landscape.jpg\",\n    \"Continue the mountain landscape with more peaks and valleys\",\n    \"your_api_key\",\n    width=1024,\n    height=768\n)\n```\n\n## Object Removal\n\n```python\ndef remove_object(image_url, object_name, api_key):\n    \"\"\"Remove a specific object from an image.\n\n    Args:\n        image_url: URL of the image\n        object_name: Name of object to remove (e.g., \"person\", \"car\", \"sign\")\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/image_editing/object_removal\",\n        json={\n            \"key\": api_key,\n            \"image\": image_url,\n            \"object_name\": object_name\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n    elif data[\"status\"] == \"processing\":\n        return poll_result(data[\"id\"], api_key)\n\n# Remove person from photo\ncleaned = remove_object(\n    \"https://example.com/photo.jpg\",\n    \"person in background\",\n    \"your_api_key\"\n)\n```\n\n## AI-Powered Image Editing (Qwen)\n\n```python\ndef edit_image_with_ai(image_url, edit_instruction, api_key):\n    \"\"\"Edit image using AI instructions.\n\n    Args:\n        image_url: URL of the image to edit\n        edit_instruction: Natural language editing instruction\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/image_editing/qwen_edit\",\n        json={\n            \"key\": api_key,\n            \"image\": image_url,\n            \"prompt\": edit_instruction,\n            \"negative_prompt\": \"low quality, distorted\",\n            \"num_inference_steps\": 30,\n            \"guidance_scale\": 7.5\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n    elif data[\"status\"] == \"processing\":\n        return poll_result(data[\"id\"], api_key)\n\n# AI-powered editing\nedited = edit_image_with_ai(\n    \"https://example.com/portrait.jpg\",\n    \"Make the background more blurred and add warm sunset lighting\",\n    \"your_api_key\"\n)\n```\n\n## Create Mask\n\n```python\ndef create_object_mask(image_url, object_description, api_key):\n    \"\"\"Create a mask for a specific object in an image.\n\n    Args:\n        image_url: URL of the image\n        object_description: What to mask (e.g., \"person\", \"car\", \"background\")\n\n    Returns:\n        URL of mask image (white = selected, black = not selected)\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/image_editing/create_mask\",\n        json={\n            \"key\": api_key,\n            \"image\": image_url,\n            \"object\": object_description\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n\n# Create mask for person\nmask_url = create_object_mask(\n    \"https://example.com/group-photo.jpg\",\n    \"person in red shirt\",\n    \"your_api_key\"\n)\n```\n\n## Polling Helper\n\n```python\nimport time\n\ndef poll_result(request_id, api_key, timeout=300):\n    \"\"\"Poll for async editing results.\"\"\"\n    start_time = time.time()\n\n    while time.time() - start_time < timeout:\n        fetch = requests.post(\n            f\"https://modelslab.com/api/v6/image_editing/fetch/{request_id}\",\n            json={\"key\": api_key}\n        )\n        result = fetch.json()\n\n        if result[\"status\"] == \"success\":\n            return result[\"output\"][0]\n        elif result[\"status\"] == \"failed\":\n            raise Exception(result.get(\"message\", \"Failed\"))\n\n        time.sleep(5)\n\n    raise Exception(\"Timeout\")\n```\n\n## Common Workflows\n\n### E-commerce Product Photos\n\n```python\ndef prepare_product_image(image_url, api_key):\n    \"\"\"Complete product photo workflow.\"\"\"\n\n    # Step 1: Remove background\n    no_bg = remove_background(image_url, api_key)\n    print(f\"Background removed: {no_bg}\")\n\n    # Step 2: Upscale to high resolution\n    hd_image = upscale_image(no_bg, api_key, scale=4)\n    print(f\"Upscaled: {hd_image}\")\n\n    return hd_image\n\nproduct_image = prepare_product_image(\n    \"https://example.com/product.jpg\",\n    \"your_api_key\"\n)\n```\n\n### Photo Cleanup\n\n```python\ndef cleanup_photo(image_url, unwanted_objects, api_key):\n    \"\"\"Remove multiple unwanted objects from photo.\"\"\"\n\n    cleaned_image = image_url\n\n    for obj in unwanted_objects:\n        cleaned_image = remove_object(cleaned_image, obj, api_key)\n        print(f\"Removed: {obj}\")\n\n    # Upscale final result\n    final = upscale_image(cleaned_image, api_key, scale=2)\n\n    return final\n\nresult = cleanup_photo(\n    \"https://example.com/vacation.jpg\",\n    [\"power lines\", \"trash can\", \"stranger in background\"],\n    \"your_api_key\"\n)\n```\n\n### Extend and Enhance\n\n```python\ndef extend_and_enhance(image_url, extension_prompt, api_key):\n    \"\"\"Extend image and upscale result.\"\"\"\n\n    # Extend the image\n    extended = extend_image(\n        image_url,\n        extension_prompt,\n        api_key,\n        width=1920,\n        height=1080\n    )\n\n    # Upscale for maximum quality\n    final = upscale_image(extended, api_key, scale=2)\n\n    return final\n```\n\n## Best Practices\n\n### 1. Background Removal\n- Works best with clear subject separation\n- Good lighting in original image helps\n- High-quality input = better output\n\n### 2. Super Resolution\n- Use 2x for moderate upscaling\n- Use 4x for maximum quality boost\n- Don't upscale already high-res images\n- Best results with clear, focused images\n\n### 3. Outpainting\n- Be specific in extension prompts\n- Match style of original image\n- Consider composition when extending\n- Test different sizes\n\n### 4. Object Removal\n- Be specific about object location\n- Works best with simple backgrounds\n- May need multiple passes for complex scenes\n\n### 5. Use Webhooks for Batch Operations\n```python\n# Process many images\nfor image in image_list:\n    response = requests.post(\n        endpoint,\n        json={\n            \"key\": api_key,\n            \"image\": image,\n            \"webhook\": \"https://yourserver.com/callback\",\n            \"track_id\": f\"img_{image_id}\"\n        }\n    )\n```\n\n## Common Use Cases\n\n### Professional Headshots\n```python\n# Remove background and upscale\nheadshot = remove_background(original, api_key)\nhd_headshot = upscale_image(headshot, api_key, scale=4)\n```\n\n### Real Estate Photos\n```python\n# Remove unwanted items\nclean_room = remove_object(\n    room_photo,\n    \"personal items and clutter\",\n    api_key\n)\n\n# Extend to show more space\nwider_view = extend_image(\n    clean_room,\n    \"Continue the modern living room with more furniture\",\n    api_key,\n    width=1920,\n    height=1080\n)\n```\n\n### Social Media Graphics\n```python\n# Upscale for quality\nhigh_res = upscale_image(graphic, api_key, scale=2)\n\n# Extend to different aspect ratios\ninstagram_square = extend_image(\n    high_res,\n    \"Extend background\",\n    api_key,\n    width=1080,\n    height=1080\n)\n```\n\n## Error Handling\n\n```python\ntry:\n    result = remove_background(image_url, api_key)\n    print(f\"Success: {result}\")\nexcept Exception as e:\n    print(f\"Editing failed: {e}\")\n    # Log error, retry, or notify user\n```\n\n## Resources\n\n- **API Documentation**: https://docs.modelslab.com/image-editing/overview\n- **Background Removal**: https://docs.modelslab.com/image-editing/removebg-createmask\n- **Super Resolution**: https://docs.modelslab.com/image-editing/super-resolution\n- **Get API Key**: https://modelslab.com/dashboard\n\n## Related Skills\n\n- `modelslab-image-generation` - Generate images to edit\n- `modelslab-webhooks` - Handle async operations\n- `modelslab-sdk-usage` - Use official SDKs\n\nFile v1.0.0:image-generation/SKILL.md\n\n---\nname: modelslab-image-generation\ndescription: Generate high-quality AI images from text prompts or transform existing images using ModelsLab's v7 API with 50,000+ models including FLUX, Realtime, and Community models. Supports text-to-image, image-to-image, inpainting, and ControlNet.\n---\n\n# ModelsLab Image Generation\n\nGenerate stunning AI images using ModelsLab's extensive library of models and powerful generation endpoints.\n\n## When to Use This Skill\n\n- Generate images from text descriptions\n- Transform or modify existing images\n- Fill in masked parts of images (inpainting)\n- Use ControlNet for precise control\n- Need fast generation (Realtime API)\n- Need highest quality (Community/FLUX models)\n- Create product images, marketing graphics, or artwork\n\n## Available APIs (v7)\n\n### 1. Text to Image\n- `POST https://modelslab.com/api/v7/images/text-to-image`\n- 50,000+ models available\n\n### 2. Image to Image\n- `POST https://modelslab.com/api/v7/images/image-to-image`\n- Transform existing images with a prompt\n\n### 3. Inpainting\n- `POST https://modelslab.com/api/v7/images/inpaint`\n- Fill masked regions of an image\n\n### 4. Fetch Result\n- `POST https://modelslab.com/api/v7/images/fetch/{id}`\n- Poll for async generation results\n\n> **Note**: v6 endpoints (`/api/v6/images/text2img`, etc.) still work but v7 is the current version.\n\n## Discovering Image Models\n\n```bash\n# Search image models by name\nmodelslab models search --feature imagen\n\n# Search specific models\nmodelslab models search --search \"flux\"\nmodelslab models search --search \"midjourney\"\n\n# Get model details\nmodelslab models detail --id flux\n```\n\n## Quick Start: Text to Image\n\n```python\nimport requests\nimport time\n\ndef generate_image(prompt, api_key, model_id=\"flux\"):\n    \"\"\"Generate an image from text.\n\n    Args:\n        prompt: Text description of the image\n        api_key: Your ModelsLab API key\n        model_id: Model to use (flux, midjourney, sdxl, imagen-3, etc.)\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v7/images/text-to-image\",\n        json={\n            \"key\": api_key,\n            \"model_id\": model_id,\n            \"prompt\": prompt,\n            \"negative_prompt\": \"blurry, low quality, distorted\",\n            \"width\": 1024,\n            \"height\": 1024,\n            \"samples\": 1,\n            \"guidance_scale\": 7.5\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n    elif data[\"status\"] == \"processing\":\n        return poll_result(data[\"id\"], api_key)\n    else:\n        raise Exception(f\"Error: {data.get('message')}\")\n\ndef poll_result(request_id, api_key, timeout=300):\n    \"\"\"Poll for async generation results.\"\"\"\n    start = time.time()\n    while time.time() - start < timeout:\n        resp = requests.post(\n            f\"https://modelslab.com/api/v7/images/fetch/{request_id}\",\n            json={\"key\": api_key}\n        )\n        data = resp.json()\n\n        if data[\"status\"] == \"success\":\n            return data[\"output\"][0]\n        elif data[\"status\"] == \"failed\":\n            raise Exception(data.get(\"message\", \"Failed\"))\n\n        time.sleep(5)\n    raise Exception(\"Timeout\")\n\n# Usage\nimage_url = generate_image(\n    \"A futuristic cityscape at sunset, cyberpunk style, 8k, highly detailed\",\n    \"your_api_key\",\n    model_id=\"flux\"\n)\nprint(f\"Image: {image_url}\")\n```\n\n## Image to Image Transformation\n\n```python\ndef transform_image(init_image, prompt, api_key, model_id=\"flux\", strength=0.7):\n    \"\"\"Transform an existing image based on a prompt.\n\n    Args:\n        init_image: URL of the input image\n        prompt: How to transform the image\n        model_id: Model to use (flux models don't need scheduler, SD models do)\n        strength: 0.0-1.0, higher = more change\n    \"\"\"\n    payload = {\n        \"key\": api_key,\n        \"model_id\": model_id,\n        \"prompt\": prompt,\n        \"init_image\": [init_image],  # v7 expects array\n        \"strength\": strength,\n        \"width\": 512,\n        \"height\": 512\n    }\n\n    response = requests.post(\n        \"https://modelslab.com/api/v7/images/image-to-image\",\n        json=payload\n    )\n\n    data = response.json()\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n    elif data[\"status\"] == \"processing\":\n        return poll_result(data[\"id\"], api_key)\n\n# Transform a photo into a painting\nresult = transform_image(\n    \"https://example.com/photo.jpg\",\n    \"An oil painting in Van Gogh style\",\n    \"your_api_key\",\n    model_id=\"flux\",\n    strength=0.8\n)\n```\n\n## Inpainting (Fill Masked Regions)\n\n```python\ndef inpaint_image(image_url, mask_url, prompt, api_key, model_id=\"flux\"):\n    \"\"\"Fill in masked parts of an image.\n\n    Args:\n        image_url: Original image URL\n        mask_url: Mask image URL (white = inpaint, black = keep)\n        prompt: What to generate in masked area\n        model_id: Model to use\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v7/images/inpaint\",\n        json={\n            \"key\": api_key,\n            \"model_id\": model_id,\n            \"init_image\": image_url,\n            \"mask_image\": mask_url,\n            \"prompt\": prompt,\n            \"negative_prompt\": \"blurry, low quality\"\n        }\n    )\n\n    data = response.json()\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n    elif data[\"status\"] == \"processing\":\n        return poll_result(data[\"id\"], api_key)\n\n# Replace object in image\nresult = inpaint_image(\n    \"https://example.com/room.jpg\",\n    \"https://example.com/mask.jpg\",\n    \"A modern red sofa\",\n    \"your_api_key\",\n    model_id=\"flux\"\n)\n```\n\n## Popular Model IDs\n\n### Premium / Fast\n- `flux` - Flux Dev (fast, high-quality, no scheduler needed)\n- `imagen-3` - Google Imagen 3 (photorealistic)\n- `imagen-4` - Google Imagen 4 (latest)\n\n### Photorealistic\n- `realistic-vision-v13` - High-quality realistic images\n- `deliberate-v2` - Versatile realistic style\n- `absolute-reality-v1.6` - Ultra-realistic outputs\n\n### Artistic/Stylized\n- `midjourney` - MidJourney-style images (most popular)\n- `dreamshaper-8` - Artistic and versatile\n- `openjourney` - Open-source MidJourney alternative\n\n### Anime/Illustration\n- `anything-v5` - Anime style\n- `counterfeit-v2.5` - Anime portraits\n- `meinamix` - High-quality anime art\n\nBrowse all models: https://modelslab.com/models\n\n## Key Parameters\n\n| Parameter | Description | Recommended Values |\n|-----------|-------------|-------------------|\n| `model_id` | Model to use (required) | `flux`, `midjourney`, `sdxl`, etc. |\n| `prompt` | Text description of desired image | Be specific and detailed |\n| `negative_prompt` | What to avoid | \"blurry, low quality, distorted\" |\n| `width` / `height` | Dimensions (512-1024) | 512, 768, 1024 |\n| `samples` | Number of images | 1-4 |\n| `guidance_scale` | Prompt adherence | 7-8 (balanced), 10-15 (strict) |\n| `seed` | Reproducibility | `null` (random) or number |\n| `strength` | img2img change amount | 0.3 (subtle), 0.7 (moderate), 0.9 (heavy) |\n| `webhook` | Async notification URL | URL string |\n| `track_id` | Custom tracking identifier | Any string |\n\n## Best Practices\n\n### 1. Craft Effective Prompts\n```\nBad: \"a car\"\nGood: \"A red Ferrari sports car, studio lighting, highly detailed, 4k, photorealistic\"\n\nInclude: Subject, style, lighting, quality descriptors\n```\n\n### 2. Use Negative Prompts\n```python\nnegative_prompt = \"blurry, low quality, distorted, deformed, ugly, bad anatomy, extra limbs\"\n```\n\n### 3. Choose Right Model\n- **flux**: Fast, high quality, good default choice\n- **midjourney**: Artistic, stylized outputs\n- **imagen-3/4**: Premium photorealistic (Google)\n- **sdxl**: Versatile base with many fine-tunes\n\n### 4. Handle Async Operations\n```python\n# Always check status and poll if needed\nif data[\"status\"] == \"processing\":\n    result = poll_result(data[\"id\"], api_key)\n```\n\n### 5. Use Webhooks for Long Operations\n```python\npayload = {\n    \"key\": api_key,\n    \"prompt\": \"...\",\n    \"webhook\": \"https://yourserver.com/webhook\",\n    \"track_id\": \"unique-identifier\"\n}\n```\n\n## Error Handling\n\n```python\ntry:\n    image = generate_image(prompt, api_key)\n    print(f\"Success: {image}\")\nexcept Exception as e:\n    print(f\"Generation failed: {e}\")\n    # Log error, retry, or notify user\n```\n\n## Resources\n\n- **API Documentation**: https://docs.modelslab.com/image-generation/overview\n- **Model Library**: https://modelslab.com/models\n- **Model Selection Guide**: https://docs.modelslab.com/guides/model-selection\n- **Get API Key**: https://modelslab.com/dashboard\n- **Community**: https://discord.gg/modelslab\n\n## Related Skills\n\n- `modelslab-model-discovery` - Find and filter models\n- `modelslab-image-editing` - Edit and enhance images\n- `modelslab-video-generation` - Generate videos from images\n- `modelslab-chat-generation` - Chat with LLM models\n- `modelslab-webhooks` - Async operation handling\n- `modelslab-sdk-usage` - Use official SDKs\n\nFile v1.0.0:interior-design/SKILL.md\n\n---\nname: modelslab-interior-design\ndescription: Transform and redesign interior spaces using ModelsLab's Interior API. Generate interior designs, decorate rooms, create floor plans, and restore exteriors with AI.\n---\n\n# ModelsLab Interior Design\n\nAI-powered interior design, room decoration, floor planning, and exterior restoration.\n\n## When to Use This Skill\n\n- Redesign interior spaces\n- Decorate rooms with AI assistance\n- Generate floor plans from images\n- Transform room styles and aesthetics\n- Restore or enhance building exteriors\n- Create design mockups and variations\n- Visualize renovation ideas\n\n## Available Endpoints\n\n### Interior Design\n`POST https://modelslab.com/api/v6/interior/interior`\n\n### Room Decorator\n`POST https://modelslab.com/api/v6/interior/room_decorator`\n\n### Floor Planning\n`POST https://modelslab.com/api/v6/interior/floor_planning`\n\n### Exterior Restorer\n`POST https://modelslab.com/api/v6/interior/exterior_restorer`\n\n### Scenario Changer\n`POST https://modelslab.com/api/v6/interior/scenario_changer`\n\n### Object Removal\n`POST https://modelslab.com/api/v6/interior/object_removal`\n\n### Interior Mixer\n`POST https://modelslab.com/api/v6/interior/interior_mixer`\n\n## Interior Redesign\n\n```python\nimport requests\n\ndef redesign_interior(room_image, design_prompt, api_key):\n    \"\"\"Redesign an interior space based on a prompt.\n\n    Args:\n        room_image: URL of the room photo\n        design_prompt: Description of desired design\n        api_key: Your ModelsLab API key\n\n    Returns:\n        URL of the redesigned interior\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/interior/interior\",\n        json={\n            \"key\": api_key,\n            \"init_image\": room_image,\n            \"prompt\": design_prompt,\n            \"negative_prompt\": \"low quality, distorted, unrealistic\",\n            \"num_inference_steps\": 31,  # 21, 31, or 41\n            \"guidance_scale\": 7.5,\n            \"strength\": 0.7\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n    else:\n        raise Exception(f\"Error: {data.get('message', 'Unknown error')}\")\n\n# Usage\nredesigned = redesign_interior(\n    \"https://example.com/living-room.jpg\",\n    \"Modern minimalist living room with Scandinavian furniture, white walls, natural light\",\n    \"your_api_key\"\n)\nprint(f\"Redesigned room: {redesigned}\")\n```\n\n## Room Decorator\n\n```python\ndef decorate_room(room_image, decor_prompt, api_key, specific_object=None):\n    \"\"\"Decorate a room with AI-generated furniture and decor.\n\n    Args:\n        room_image: URL of the empty or basic room\n        decor_prompt: Description of desired decoration\n        specific_object: Specific furniture/decor item that must appear\n    \"\"\"\n    payload = {\n        \"key\": api_key,\n        \"init_image\": room_image,\n        \"prompt\": decor_prompt,\n        \"negative_prompt\": \"cluttered, low quality, distorted\",\n        \"num_inference_steps\": 31,\n        \"guidance_scale\": 7.5,\n        \"strength\": 0.8\n    }\n\n    if specific_object:\n        payload[\"specific_object\"] = specific_object\n\n    response = requests.post(\n        \"https://modelslab.com/api/v6/interior/room_decorator\",\n        json=payload\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n    else:\n        raise Exception(data.get(\"message\"))\n\n# Decorate empty room\ndecorated = decorate_room(\n    \"https://example.com/empty-room.jpg\",\n    \"Cozy bedroom with warm lighting, plants, wooden furniture\",\n    \"your_api_key\",\n    specific_object=\"king size bed\"\n)\nprint(f\"Decorated room: {decorated}\")\n```\n\n## Floor Planning\n\n```python\ndef generate_floor_plan(room_image, api_key):\n    \"\"\"Generate a floor plan from a room image.\n\n    Args:\n        room_image: URL of room photo\n        api_key: Your API key\n\n    Returns:\n        URL of the generated floor plan\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/interior/floor_planning\",\n        json={\n            \"key\": api_key,\n            \"init_image\": room_image\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n    else:\n        raise Exception(data.get(\"message\"))\n\n# Generate floor plan\nfloor_plan = generate_floor_plan(\n    \"https://example.com/room-photo.jpg\",\n    \"your_api_key\"\n)\nprint(f\"Floor plan: {floor_plan}\")\n```\n\n## Exterior Restoration\n\n```python\ndef restore_exterior(building_image, restoration_prompt, api_key):\n    \"\"\"Restore or enhance building exterior.\n\n    Args:\n        building_image: URL of building exterior photo\n        restoration_prompt: Description of desired restoration\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/interior/exterior_restorer\",\n        json={\n            \"key\": api_key,\n            \"init_image\": building_image,\n            \"prompt\": restoration_prompt,\n            \"negative_prompt\": \"damaged, old, worn\",\n            \"num_inference_steps\": 31,\n            \"guidance_scale\": 7.5\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n    else:\n        raise Exception(data.get(\"message\"))\n\n# Restore old building\nrestored = restore_exterior(\n    \"https://example.com/old-building.jpg\",\n    \"Restored Victorian house with fresh paint, new windows, landscaped garden\",\n    \"your_api_key\"\n)\n```\n\n## Scenario Changer\n\n```python\ndef change_room_scenario(room_image, new_scenario, api_key):\n    \"\"\"Change the environment scenario of a room.\n\n    Args:\n        room_image: URL of room photo\n        new_scenario: Description of new scenario/ambiance\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/interior/scenario_changer\",\n        json={\n            \"key\": api_key,\n            \"init_image\": room_image,\n            \"prompt\": new_scenario,\n            \"num_inference_steps\": 31,\n            \"guidance_scale\": 7.5\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n    else:\n        raise Exception(data.get(\"message\"))\n\n# Change from day to evening\nevening_room = change_room_scenario(\n    \"https://example.com/daytime-room.jpg\",\n    \"Evening ambiance with warm lamp lighting, cozy atmosphere\",\n    \"your_api_key\"\n)\n```\n\n## Object Removal\n\n```python\ndef remove_interior_object(room_image, object_to_remove, api_key):\n    \"\"\"Remove an object from an interior image.\n\n    Args:\n        room_image: URL of room photo\n        object_to_remove: Description of object to remove\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/interior/object_removal\",\n        json={\n            \"key\": api_key,\n            \"init_image\": room_image,\n            \"object_name\": object_to_remove\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n    else:\n        raise Exception(data.get(\"message\"))\n\n# Remove furniture\ncleaned = remove_interior_object(\n    \"https://example.com/cluttered-room.jpg\",\n    \"old sofa\",\n    \"your_api_key\"\n)\n```\n\n## Interior Mixer\n\n```python\ndef mix_interior_objects(room_image, object_image, placement_prompt, api_key):\n    \"\"\"Add objects from one image into another room.\n\n    Args:\n        room_image: URL of the target room\n        object_image: URL of image containing object to add\n        placement_prompt: Description of how to place the object\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/interior/interior_mixer\",\n        json={\n            \"key\": api_key,\n            \"init_image\": room_image,\n            \"object_image\": object_image,\n            \"prompt\": placement_prompt,\n            \"width\": 512,\n            \"height\": 512,\n            \"num_inference_steps\": 8,\n            \"guidance_scale\": 7.5\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n    else:\n        raise Exception(data.get(\"message\"))\n\n# Add furniture from another image\nmixed = mix_interior_objects(\n    \"https://example.com/empty-room.jpg\",\n    \"https://example.com/furniture.jpg\",\n    \"Place the chair in the corner near the window\",\n    \"your_api_key\"\n)\n```\n\n## Key Parameters\n\n| Parameter | Description | Values |\n|-----------|-------------|--------|\n| `init_image` | Room/building image | Image URL |\n| `prompt` | Design description | Detailed text |\n| `negative_prompt` | What to avoid | \"cluttered, low quality\" |\n| `strength` | Transformation strength | 0.0-1.0 (0.7 typical) |\n| `num_inference_steps` | Quality level | 21, 31, or 41 |\n| `guidance_scale` | Prompt adherence | 1-20 (7.5 typical) |\n| `specific_object` | Required item | Object name |\n| `object_name` | Object to remove | Description |\n\n## Best Practices\n\n### 1. Write Detailed Design Prompts\n```\n✗ Bad: \"modern room\"\n✓ Good: \"Modern minimalist living room with Scandinavian furniture, white walls, oak floor, large windows, indoor plants\"\n\nInclude: Style, furniture, colors, lighting, materials, atmosphere\n```\n\n### 2. Use Appropriate Strength Values\n```python\n# Subtle changes\nstrength = 0.5\n\n# Moderate redesign\nstrength = 0.7\n\n# Complete transformation\nstrength = 0.9\n```\n\n### 3. Quality vs Speed\n```python\n# Fast (21 steps)\nnum_inference_steps = 21\n\n# Balanced (31 steps) - Recommended\nnum_inference_steps = 31\n\n# Best quality (41 steps)\nnum_inference_steps = 41\n```\n\n### 4. Use High-Quality Input Images\n- Well-lit room photos\n- Clear view of the space\n- Minimal distortion\n- High resolution preferred\n\n## Common Use Cases\n\n### Virtual Staging\n\n```python\ndef stage_empty_room(room_image, style, api_key):\n    \"\"\"Stage an empty room for real estate listing.\"\"\"\n    return decorate_room(\n        room_image,\n        f\"{style} furnished room with modern furniture, well-lit, professional\",\n        api_key\n    )\n\n# Stage for listing\nstaged = stage_empty_room(\n    \"https://example.com/empty-apartment.jpg\",\n    \"Modern luxury\",\n    api_key\n)\n```\n\n### Design Variations\n\n```python\ndef create_design_variations(room_image, styles, api_key):\n    \"\"\"Generate multiple design style variations.\"\"\"\n    variations = []\n\n    for style in styles:\n        variant = redesign_interior(\n            room_image,\n            f\"{style} interior design style\",\n            api_key\n        )\n        variations.append(variant)\n        print(f\"{style}: {variant}\")\n\n    return variations\n\n# Generate variations\ndesigns = create_design_variations(\n    \"https://example.com/room.jpg\",\n    [\"Modern Scandinavian\", \"Industrial Loft\", \"Classic Traditional\", \"Bohemian\"],\n    api_key\n)\n```\n\n### Renovation Planning\n\n```python\ndef plan_renovation(current_room, desired_style, api_key):\n    \"\"\"Plan room renovation with before/after.\"\"\"\n    before = current_room\n\n    after = redesign_interior(\n        before,\n        f\"Renovated {desired_style} room with updated fixtures and furniture\",\n        api_key\n    )\n\n    return {\"before\": before, \"after\": after}\n\n# Plan kitchen renovation\nplan = plan_renovation(\n    \"https://example.com/old-kitchen.jpg\",\n    \"modern farmhouse kitchen\",\n    api_key\n)\n```\n\n### Complete Room Makeover\n\n```python\ndef complete_room_makeover(room_image, api_key):\n    \"\"\"Full room transformation workflow.\"\"\"\n\n    # Step 1: Remove unwanted items\n    cleaned = remove_interior_object(\n        room_image,\n        \"old furniture and clutter\",\n        api_key\n    )\n\n    # Step 2: Redesign space\n    redesigned = redesign_interior(\n        cleaned,\n        \"Modern minimalist interior with natural materials\",\n        api_key\n    )\n\n    # Step 3: Add specific decor\n    final = decorate_room(\n        redesigned,\n        \"Add cozy lighting and indoor plants\",\n        api_key,\n        specific_object=\"pendant lamp\"\n    )\n\n    return final\n```\n\n### Before/After Scenarios\n\n```python\n# Day to night transformation\nday_room = \"https://example.com/daytime.jpg\"\n\nnight = change_room_scenario(\n    day_room,\n    \"Evening ambiance with warm lighting, twilight outside windows\",\n    api_key\n)\n\n# Summer to winter\nwinter = change_room_scenario(\n    day_room,\n    \"Winter scene with snow outside, cozy fireplace, warm interior\",\n    api_key\n)\n```\n\n## Error Handling\n\n```python\ntry:\n    design = redesign_interior(room_image, prompt, api_key)\n    print(f\"Design created: {design}\")\nexcept Exception as e:\n    print(f\"Design generation failed: {e}\")\n    # Log error, try different prompt, notify user\n```\n\n## Performance Tips\n\n1. **Use Appropriate Inference Steps**: 31 steps balances quality and speed\n2. **Optimize Prompts**: Clear, detailed prompts work best\n3. **Batch Similar Requests**: Generate multiple variations together\n4. **Cache Results**: Store generated designs\n5. **Monitor Quality**: Adjust strength and guidance_scale as needed\n\n## Enterprise API\n\nFor dedicated resources:\n\n```python\n# Enterprise endpoints\nurl = \"https://modelslab.com/api/v1/enterprise/interior/interior\"\nurl = \"https://modelslab.com/api/v1/enterprise/interior/room_decorator\"\n```\n\n## Resources\n\n- **Interior API Docs**: https://docs.modelslab.com/interior-api/overview\n- **Interior Design**: https://docs.modelslab.com/interior-api/interior\n- **Room Decorator**: https://docs.modelslab.com/interior-api/room-decorator\n- **Floor Planning**: https://docs.modelslab.com/interior-api/floor-planning\n- **Get API Key**: https://modelslab.com/dashboard\n\n## Related Skills\n\n- `modelslab-image-generation` - Generate room reference images\n- `modelslab-image-editing` - Additional editing tools\n- `modelslab-sdk-usage` - Use official SDKs\n\nFile v1.0.0:model-discovery/SKILL.md\n\n---\nname: modelslab-model-discovery\ndescription: Search and discover 50,000+ AI models on ModelsLab, check usage analytics, and monitor generation history via the Agent Control Plane API.\n---\n\n# ModelsLab Model Discovery & Usage\n\nSearch 50,000+ AI models, check usage analytics, and monitor generation history via the Agent Control Plane API.\n\n## When to Use This Skill\n\n- Search for models by name, feature, provider, or tags\n- Find the best model for a specific task (image, video, audio, LLM)\n- Get model details (capabilities, parameters, pricing)\n- Check API usage summary and credit consumption\n- View generation history with date filters\n- Browse available model filters, tags, and providers\n\n## Authentication\n\nAll endpoints require a bearer token.\n\n```\nBase URL: https://modelslab.com/api/agents/v1\nAuthorization: Bearer <agent_access_token>\n```\n\nGet a token via the `modelslab-account-management` skill or `POST /auth/login`.\n\n## Helper\n\n```python\nimport requests\n\nBASE = \"https://modelslab.com/api/agents/v1\"\n\ndef headers(token):\n    return {\"Authorization\": f\"Bearer {token}\"}\n```\n\n## Model Search\n\n### Search Models\n\n```python\ndef search_models(token, search=None, feature=None, provider=None,\n                  model_type=None, base_model=None, tags=None,\n                  sort=\"recommended\", per_page=20):\n    \"\"\"Search the ModelsLab model library.\n\n    Args:\n        search: Free text search query\n        feature: Filter by feature — \"imagen\", \"video_fusion\", \"audio_gen\",\n                 \"llmaster\", \"threed\", \"interior\", \"deepfake\"\n        provider: Filter by provider name\n        model_type: Filter by model type\n        base_model: Filter by base model (e.g., \"SDXL\", \"Flux\")\n        tags: Comma-separated tags\n        sort: \"recommended\" (default), \"newest\", \"popular\"\n        per_page: Results per page (default 20)\n    \"\"\"\n    params = {\"sort\": sort, \"per_page\": per_page}\n    if search: params[\"search\"] = search\n    if feature: params[\"feature\"] = feature\n    if provider: params[\"provider\"] = provider\n    if model_type: params[\"model_type\"] = model_type\n    if base_model: params[\"base_model\"] = base_model\n    if tags: params[\"tags\"] = tags\n\n    resp = requests.get(\n        f\"{BASE}/models\",\n        headers=headers(token),\n        params=params\n    )\n    return resp.json()[\"data\"]\n\n# Search for Flux image models\nmodels = search_models(token, search=\"flux\", feature=\"imagen\", sort=\"popular\")\nfor m in models:\n    print(f\"{m['model_id']}: {m['name']}\")\n```\n\n### Search by Feature\n\n```python\n# Image generation models\nimage_models = search_models(token, feature=\"imagen\", per_page=10)\n\n# Video generation models\nvideo_models = search_models(token, feature=\"video_fusion\", per_page=10)\n\n# Audio generation models\naudio_models = search_models(token, feature=\"audio_gen\", per_page=10)\n\n# LLM / Chat models\nllm_models = search_models(token, feature=\"llmaster\", per_page=10)\n\n# 3D generation models\nthreed_models = search_models(token, feature=\"threed\", per_page=10)\n\n# Interior design models\ninterior_models = search_models(token, feature=\"interior\", per_page=10)\n```\n\n### Get Model Details\n\n```python\ndef get_model_detail(token, model_id):\n    \"\"\"Get full details for a specific model.\n\n    Returns: capabilities, endpoint configurations with agent-friendly\n    `parameters` JSON Schema (types, constraints, defaults), pricing, etc.\n    \"\"\"\n    resp = requests.get(\n        f\"{BASE}/models/{model_id}\",\n        headers=headers(token)\n    )\n    return resp.json()[\"data\"]\n\n# Usage\nmodel = get_model_detail(token, \"flux-dev\")\nprint(f\"Name: {model['name']}\")\nprint(f\"Type: {model.get('model_type')}\")\nprint(f\"Provider: {model.get('provider')}\")\n\n# Access agent-friendly parameters for each endpoint\nfor ep in model.get(\"endpoint_configurations\", []):\n    params = ep.get(\"parameters\")\n    if params:\n        print(f\"\\nEndpoint: {ep['name']}\")\n        for name, schema in params[\"properties\"].items():\n            print(f\"  {name}: {schema['type']}\", end=\"\")\n            if \"enum\" in schema:\n                print(f\" (options: {schema['enum']})\", end=\"\")\n            if \"default\" in schema:\n                print(f\" [default: {schema['default']}]\", end=\"\")\n            print()\n```\n\n### Browse Filters, Tags, Providers\n\n```python\ndef get_model_filters(token):\n    \"\"\"Get all available filter options (features, types, categories).\"\"\"\n    resp = requests.get(f\"{BASE}/models/filters\", headers=headers(token))\n    return resp.json()[\"data\"]\n\ndef get_model_tags(token):\n    \"\"\"Get all available model tags.\"\"\"\n    resp = requests.get(f\"{BASE}/models/tags\", headers=headers(token))\n    return resp.json()[\"data\"]\n\ndef get_model_providers(token):\n    \"\"\"Get all model providers.\"\"\"\n    resp = requests.get(f\"{BASE}/models/providers\", headers=headers(token))\n    return resp.json()[\"data\"]\n\n# Usage\nfilters = get_model_filters(token)\ntags = get_model_tags(token)\nproviders = get_model_providers(token)\nprint(f\"Available features: {[f['name'] for f in filters.get('features', [])]}\")\nprint(f\"Top tags: {tags[:10]}\")\nprint(f\"Providers: {[p['name'] for p in providers]}\")\n```\n\n## Usage Analytics\n\n### Usage Summary\n\n```python\ndef get_usage_summary(token):\n    \"\"\"Get overall API usage summary — total calls, credits used, etc.\"\"\"\n    resp = requests.get(f\"{BASE}/usage/summary\", headers=headers(token))\n    return resp.json()[\"data\"]\n\n# Usage\nsummary = get_usage_summary(token)\nprint(f\"Total API calls: {summary.get('total_calls', 0)}\")\nprint(f\"Credits used: {summary.get('credits_used', 0)}\")\n```\n\n### Usage by Product\n\n```python\ndef get_usage_by_product(token):\n    \"\"\"Get usage breakdown by product (image, video, audio, etc.).\"\"\"\n    resp = requests.get(f\"{BASE}/usage/products\", headers=headers(token))\n    return resp.json()[\"data\"]\n\n# Usage\nproducts = get_usage_by_product(token)\nfor product in products:\n    print(f\"{product['name']}: {product.get('calls', 0)} calls\")\n```\n\n### Generation History\n\n```python\ndef get_usage_history(token, from_date=None, to_date=None, limit=100):\n    \"\"\"Get detailed generation history with optional date filters.\n\n    Args:\n        from_date: Start date (YYYY-MM-DD)\n        to_date: End date (YYYY-MM-DD)\n        limit: Max items (1-200, default 100)\n    \"\"\"\n    params = {\"limit\": limit}\n    if from_date: params[\"from\"] = from_date\n    if to_date: params[\"to\"] = to_date\n\n    resp = requests.get(\n        f\"{BASE}/usage/history\",\n        headers=headers(token),\n        params=params\n    )\n    return resp.json()[\"data\"]\n\n# Get last 7 days of history\nhistory = get_usage_history(token, from_date=\"2025-01-01\", to_date=\"2025-01-07\")\nfor item in history:\n    print(f\"{item['created_at']}: {item.get('endpoint')} - {item.get('status')}\")\n```\n\n## Common Workflows\n\n### Find Best Model for a Task\n\n```python\ndef find_best_model(token, task_description, feature):\n    \"\"\"Search for the best model for a given task.\"\"\"\n    models = search_models(\n        token,\n        search=task_description,\n        feature=feature,\n        sort=\"recommended\",\n        per_page=5\n    )\n\n    if not models:\n        print(\"No models found. Try broader search terms.\")\n        return None\n\n    best = models[0]\n    print(f\"Recommended: {best['model_id']} — {best['name']}\")\n    return best[\"model_id\"]\n\n# Find best model for realistic portraits\nmodel_id = find_best_model(token, \"realistic portrait photography\", \"imagen\")\n\n# Find best video model\nmodel_id = find_best_model(token, \"text to video cinematic\", \"video_fusion\")\n```\n\n### Monitor Usage and Alerts\n\n```python\ndef check_usage_health(token, max_daily_spend=100):\n    \"\"\"Monitor usage and alert if spending too fast.\"\"\"\n    from datetime import date\n\n    today = date.today().isoformat()\n    history = get_usage_history(token, from_date=today, to_date=today)\n\n    daily_cost = sum(item.get(\"cost\", 0) for item in history)\n    daily_calls = len(history)\n\n    print(f\"Today: {daily_calls} API calls, ${daily_cost:.2f} spent\")\n\n    if daily_cost > max_daily_spend:\n        print(f\"WARNING: Daily spend ${daily_cost:.2f} exceeds ${max_daily_spend}\")\n        return False\n    return True\n```\n\n### Complete Model Selection Pipeline\n\n```python\ndef select_model_for_generation(token, prompt, media_type=\"image\"):\n    \"\"\"Full pipeline: search models, check usage, select best model.\"\"\"\n\n    # Map media type to feature\n    feature_map = {\n        \"image\": \"imagen\",\n        \"video\": \"video_fusion\",\n        \"audio\": \"audio_gen\",\n        \"3d\": \"threed\",\n        \"chat\": \"llmaster\"\n    }\n    feature = feature_map.get(media_type, \"imagen\")\n\n    # Search models\n    models = search_models(token, search=prompt, feature=feature, per_page=5)\n\n    if not models:\n        # Fallback: search without prompt\n        models = search_models(token, feature=feature, sort=\"popular\", per_page=5)\n\n    # Check usage\n    summary = get_usage_summary(token)\n    print(f\"Credits remaining: {summary.get('credits_remaining', 'N/A')}\")\n\n    # Return top model\n    if models:\n        model = models[0]\n        print(f\"Selected: {model['model_id']} ({model['name']})\")\n        return model[\"model_id\"]\n    return None\n\n# Usage\nmodel_id = select_model_for_generation(token, \"anime character\", \"image\")\n```\n\n## MCP Server Access\n\nThese same capabilities are available via the Agent Control Plane MCP server:\n- **URL**: `https://modelslab.com/mcp/agents`\n- **Tools**: `agent-models`, `agent-usage`\n\nSee: https://docs.modelslab.com/mcp-web-api/agent-control-plane\n\n## API Endpoints Reference\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| GET | `/models` | Search models |\n| GET | `/models/filters` | Available filter options |\n| GET | `/models/tags` | Available tags |\n| GET | `/models/providers` | Available providers |\n| GET | `/models/{modelId}` | Model details |\n| GET | `/usage/summary` | Usage summary |\n| GET | `/usage/products` | Usage by product |\n| GET | `/usage/history` | Generation history |\n\n## Feature Values\n\nUse these feature values when filtering models:\n\n| Feature | Description |\n|---------|-------------|\n| `imagen` | Image generation (text-to-image, img-to-img) |\n| `video_fusion` | Video generation (text-to-video, img-to-video) |\n| `audio_gen` | Audio generation (TTS, music, SFX, voice cloning) |\n| `llmaster` | LLM / Chat completions |\n| `threed` | 3D model generation |\n| `interior` | Interior design |\n| `deepfake` | Face swap / Deepfake |\n\n## Best Practices\n\n### 1. Use Feature Filters\n```python\n# More efficient than broad text search\nmodels = search_models(token, feature=\"imagen\", sort=\"popular\")\n```\n\n### 2. Cache Model Lists\n```python\n# Model lists don't change frequently\nimport functools\n\n@functools.lru_cache(maxsize=32)\ndef cached_search(feature, sort=\"recommended\"):\n    return search_models(token, feature=feature, sort=sort)\n```\n\n### 3. Check Model Details Before Using\n```python\ndetail = get_model_detail(token, model_id)\n# Verify model supports your use case, check pricing, etc.\n```\n\n### 4. Monitor Usage Regularly\n```python\n# Set up daily usage checks\nsummary = get_usage_summary(token)\nif summary.get(\"credits_remaining\", 0) < 100:\n    print(\"Low credits — consider topping up wallet\")\n```\n\n## Resources\n\n- **API Documentation**: https://docs.modelslab.com/agents-api/usage-and-models\n- **Model Library**: https://modelslab.com/models\n- **MCP Server**: https://docs.modelslab.com/mcp-web-api/agent-control-plane\n- **Dashboard**: https://modelslab.com/dashboard\n\n## Related Skills\n\n- `modelslab-account-management` - Account setup, API keys, teams\n- `modelslab-billing-subscriptions` - Wallet funding and subscriptions\n- `modelslab-image-generation` - Use discovered models for image generation\n- `modelslab-video-generation` - Use discovered models for video generation\n\nFile v1.0.0:sdk-usage/SKILL.md\n\n---\nname: modelslab-sdk-usage\ndescription: Use ModelsLab's official SDKs (Python, TypeScript, PHP, Go, Dart) for easier integration with type safety, better error handling, and cleaner code.\n---\n\n# ModelsLab SDK Usage\n\nOfficial SDKs for Python, TypeScript/JavaScript, PHP, Go, and Dart with type safety and better developer experience.\n\n## When to Use SDKs\n\n- Want type safety and autocomplete\n- Prefer object-oriented interfaces\n- Need better error handling\n- Building production applications\n- Want cleaner, more maintainable code\n- Working in typed languages\n\n## Available SDKs\n\n### Python\n```bash\npip install modelslab-py\n```\n\n### TypeScript/JavaScript\n```bash\nnpm install modelslab\n# or\nyarn add modelslab\n```\n\n### PHP\n```bash\ncomposer require modelslab/modelslab-php\n```\n\n### Go\n```bash\ngo get github.com/modelslab/modelslab-go\n```\n\n### Dart/Flutter\n```bash\ndart pub add modelslab\n# or add to pubspec.yaml\n```\n\n## Python SDK\n\n### Installation & Setup\n\n```python\nfrom modelslab_py.core.client import Client\nfrom modelslab_py.core.apis.realtime import Realtime\nfrom modelslab_py.schemas.realtime import Text2ImageSchema\n\n# Initialize client\nclient = Client(api_key=\"your_api_key\")\n\n# Create API instance\nrealtime_api = Realtime(client=client, enterprise=False)\n```\n\n### Image Generation\n\n```python\nfrom modelslab_py.core.apis.community import Community\nfrom modelslab_py.schemas.community import Text2ImageSchema\n\n# Community models\ncommunity_api = Community(client=client, enterprise=False)\n\nschema = Text2ImageSchema(\n    model_id=\"midjourney\",\n    prompt=\"A futuristic cityscape at sunset, cyberpunk style\",\n    negative_prompt=\"blurry, low quality\",\n    width=768,\n    height=768,\n    samples=1,\n    num_inference_steps=30,\n    guidance_scale=7.5,\n    safety_checker=\"yes\"\n)\n\nresponse = community_api.text_to_image(schema)\nprint(f\"Image URL: {response['output'][0]}\")\n```\n\n### Video Generation\n\n```python\nfrom modelslab_py.core.apis.video import Video\nfrom modelslab_py.schemas.video import Text2Video\n\nvideo_api = Video(client=client, enterprise=False)\n\nschema = Text2Video(\n    model_id=\"cogvideox\",\n    prompt=\"A spaceship flying through space\",\n    width=512,\n    height=512,\n    num_frames=25,\n    num_inference_steps=20\n)\n\nresponse = video_api.text_to_video(schema)\nprint(f\"Video: {response}\")\n```\n\n### Audio Generation\n\n```python\nfrom modelslab_py.core.apis.audio import Audio\nfrom modelslab_py.schemas.audio import Text2Speech\n\naudio_api = Audio(client=client, enterprise=False)\n\nschema = Text2Speech(\n    text=\"Hello, welcome to ModelsLab!\",\n    voice_id=\"alloy\",\n    language=\"en\"\n)\n\nresponse = audio_api.text_to_speech(schema)\nprint(f\"Audio: {response['output'][0]}\")\n```\n\n### Image Editing\n\n```python\nfrom modelslab_py.core.apis.image_editing import Image_editing\nfrom modelslab_py.schemas.image_editing import (\n    BackgroundRemoverSchema,\n    SuperResolutionSchema\n)\n\nediting_api = Image_editing(client=client, enterprise=False)\n\n# Remove background\nbg_schema = BackgroundRemoverSchema(\n    image=\"https://example.com/photo.jpg\"\n)\nresult = editing_api.background_remover(bg_schema)\n\n# Upscale\nupscale_schema = SuperResolutionSchema(\n    image=\"https://example.com/image.jpg\",\n    scale=4\n)\nhd_image = editing_api.super_resolution(upscale_schema)\n```\n\n### 3D Generation\n\n```python\nfrom modelslab_py.core.apis.three_d import Three_D\nfrom modelslab_py.schemas.threed import Text23D, Image23D\n\nthreed_api = Three_D(client=client, enterprise=False)\n\n# Text to 3D\nschema = Text23D(\n    prompt=\"A medieval sword with ornate handle\",\n    num_inference_steps=50\n)\nresponse = threed_api.text_to_3d(schema)\n\n# Image to 3D\nimg_schema = Image23D(\n    image=\"https://example.com/product.jpg\"\n)\nmodel = threed_api.image_to_3d(img_schema)\n```\n\n## TypeScript/JavaScript SDK\n\n### Installation & Setup\n\n```typescript\nimport { Client, Realtime, Community, Video } from \"modelslab\";\n\n// Initialize client\nconst client = new Client(\"your_api_key\");\n```\n\n### Image Generation\n\n```typescript\nimport { Community } from \"modelslab\";\n\nconst community = new Community(client.key);\n\nconst result = await community.textToImage({\n  key: client.key,\n  model_id: \"midjourney\",\n  prompt: \"A futuristic cityscape\",\n  negative_prompt: \"blurry, low quality\",\n  width: 768,\n  height: 768,\n  samples: 1,\n  num_inference_steps: 30,\n  guidance_scale: 7.5\n});\n\nconsole.log(\"Image:\", result.output[0]);\n```\n\n### Video Generation\n\n```typescript\nimport { Video } from \"modelslab\";\n\nconst video = new Video(client.key);\n\nconst result = await video.textToVideo({\n  key: client.key,\n  model_id: \"cogvideox\",\n  prompt: \"A spaceship flying through space\",\n  num_frames: 25,\n  num_inference_steps: 20\n});\n\nconsole.log(\"Video:\", result);\n```\n\n### Audio Generation\n\n```typescript\nimport { Audio } from \"modelslab\";\n\nconst audio = new Audio(client.key);\n\nconst result = await audio.textToSpeech({\n  key: client.key,\n  text: \"Hello, welcome to ModelsLab!\",\n  voice_id: \"alloy\",\n  language: \"en\"\n});\n\nconsole.log(\"Audio:\", result.output[0]);\n```\n\n### Deepfake\n\n```typescript\nimport { DeepFake } from \"modelslab\";\n\nconst deepfake = new DeepFake(client.key);\n\nconst result = await deepfake.specificFaceSwap({\n  key: client.key,\n  init_image: \"https://example.com/target.jpg\",\n  target_image: \"https://example.com/face.jpg\"\n});\n\nconsole.log(\"Face swap:\", result.output[0]);\n```\n\n## PHP SDK\n\n### Installation & Setup\n\n```php\n<?php\nuse ModelsLab\\ModelsLab;\nuse ModelsLab\\Schemas\\Text2ImageSchema;\n\n$modelslab = new ModelsLab('your-api-key');\n```\n\n### Image Generation\n\n```php\n<?php\nuse ModelsLab\\Schemas\\Text2ImageSchema;\n\n$schema = new Text2ImageSchema([\n    'model_id' => 'midjourney',\n    'prompt' => 'A futuristic cityscape',\n    'negative_prompt' => 'blurry, low quality',\n    'width' => 768,\n    'height' => 768,\n    'num_inference_steps' => 30\n]);\n\n$response = $modelslab->community()->textToImage($schema);\necho \"Image: \" . $response['output'][0];\n```\n\n### Video Generation\n\n```php\n<?php\nuse ModelsLab\\Schemas\\Text2Video;\n\n$video = new Text2Video([\n    'prompt' => 'A spaceship flying through space',\n    'model_id' => 'cogvideox',\n    'num_frames' => 25\n]);\n\n$response = $mo","readmeExcerpt":"Skill: Modelslab : Generate Video, Images, LLMs using CLI and APIs Owner: adhikjoshi Summary: Access ModelsLab's full AI platform via CLI and APIs to generate images, videos, audio, 3D models, deepfakes, manage accounts, billing, and discover AI models. Tags: latest:1.0.0 Version history: v1.0.0 | 2026-03-04T20:03:38.830Z | user Initial release of the ModelsLab agent skills. - Provides official agent skills for Model","codeSnippets":[],"executableExamples":[{"language":"python","snippet":"import requests\nimport time\n\ndef text_to_3d(prompt, api_key, num_inference_steps=50):\n    \"\"\"Generate a 3D object from a text prompt.\n\n    Args:\n        prompt: Text description of the 3D object\n        api_key: Your ModelsLab API key\n        num_inference_steps: Quality (higher = better, slower)\n\n    Returns:\n        URL of the 3D model file\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/3d/text_to_3d\",\n        json={\n            \"key\": api_key,\n            \"prompt\": prompt,\n            \"num_inference_steps\": num_inference_steps\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"error\":\n        raise Exception(f\"Error: {data['message']}\")\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n\n    # 3D generation is async - poll for results\n    request_id = data[\"id\"]\n    print(f\"3D generation started... Request ID: {request_id}\")\n    print(f\"ETA: {data.get('eta', 'unknown')} seconds\")\n\n    return poll_3d_result(request_id, api_key)\n\ndef poll_3d_result(request_id, api_key, timeout=600):\n    \"\"\"Poll for 3D generation results.\"\"\"\n    start_time = time.time()\n\n    while time.time() - start_time < timeout:\n        fetch = requests.post(\n            f\"https://modelslab.com/api/v6/3d/fetch/{request_id}\",\n            json={\"key\": api_key}\n        )\n        result = fetch.json()\n\n        if result[\"status\"] == \"success\":\n            return result[\"output\"][0]\n        elif result[\"status\"] == \"failed\":\n            raise Exception(result.get(\"message\", \"Generation failed\"))\n\n        print(f\"Status: processing... ({int(time.time() - start_time)}s elapsed)\")\n        time.sleep(10)\n\n    raise Exception(\"Timeout waiting for 3D generation\")\n\n# Usage\nmodel_url = text_to_3d(\n    \"A medieval sword with ornate handle and detailed engravings\",\n    \"your_api_key\",\n    num_inference_steps=50\n)\nprint(f\"3D model ready: {model_url}\")"},{"language":"python","snippet":"def image_to_3d(image_url, api_key):\n    \"\"\"Convert a 2D image into a 3D model.\n\n    Args:\n        image_url: URL of the 2D image\n        api_key: Your ModelsLab API key\n\n    Returns:\n        URL of the generated 3D model\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/3d/image_to_3d\",\n        json={\n            \"key\": api_key,\n            \"image\": image_url\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"error\":\n        raise Exception(f\"Error: {data['message']}\")\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n\n    # Poll for results\n    request_id = data[\"id\"]\n    print(f\"Converting image to 3D... Request ID: {request_id}\")\n\n    return poll_3d_result(request_id, api_key)\n\n# Convert product photo to 3D\nmodel_url = image_to_3d(\n    \"https://example.com/product-photo.jpg\",\n    \"your_api_key\"\n)\nprint(f\"3D model: {model_url}\")"},{"language":"python","snippet":"def generate_3d_with_webhook(prompt, api_key, webhook_url, track_id):\n    \"\"\"Generate 3D model and receive results via webhook.\"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/3d/text_to_3d\",\n        json={\n            \"key\": api_key,\n            \"prompt\": prompt,\n            \"num_inference_steps\": 50,\n            \"webhook\": webhook_url,\n            \"track_id\": track_id\n        }\n    )\n\n    data = response.json()\n    print(f\"Request submitted: {data['id']}\")\n    return data[\"id\"]\n\n# Usage\nrequest_id = generate_3d_with_webhook(\n    \"A futuristic sci-fi weapon\",\n    \"your_api_key\",\n    \"https://yourserver.com/webhook/3d\",\n    \"model_001\"\n)"},{"language":"text","snippet":"✗ Bad: \"a chair\"\n✓ Good: \"A modern office chair with ergonomic design, armrests, five wheels, mesh back\"\n\nInclude: Type, style, materials, key features, details"},{"language":"python","snippet":"# 3D generation is ALWAYS async\nif data[\"status\"] == \"processing\":\n    result = poll_3d_result(data[\"id\"], api_key)"},{"language":"python","snippet":"# Use longer timeouts for 3D\npoll_3d_result(request_id, api_key, timeout=900)  # 15 minutes\n\n# Or use webhooks\ngenerate_3d_with_webhook(prompt, api_key, webhook_url, track_id)"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"3d-generation/SKILL.md","content":"---\nname: modelslab-3d-generation\ndescription: Generate 3D models and objects from text prompts or images using ModelsLab's 3D API. Transform 2D images into 3D representations or create 3D objects from text descriptions.\n---\n\n# ModelsLab 3D Generation\n\nTransform text descriptions and 2D images into 3D models using AI-powered 3D generation.\n\n## When to Use This Skill\n\n- Generate 3D models from text descriptions\n- Convert 2D images to 3D representations\n- Create 3D assets for games or applications\n- Prototype 3D objects quickly\n- Generate 3D product mockups\n- Create 3D characters from photos\n\n## Available Endpoints\n\n### Text to 3D\n`POST https://modelslab.com/api/v6/3d/text_to_3d`\n\n### Image to 3D\n`POST https://modelslab.com/api/v6/3d/image_to_3d`\n\n## Text to 3D\n\n```python\nimport requests\nimport time\n\ndef text_to_3d(prompt, api_key, num_inference_steps=50):\n    \"\"\"Generate a 3D object from a text prompt.\n\n    Args:\n        prompt: Text description of the 3D object\n        api_key: Your ModelsLab API key\n        num_inference_steps: Quality (higher = better, slower)\n\n    Returns:\n        URL of the 3D model file\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v6/3d/text_to_3d\",\n        json={\n            \"key\": api_key,\n            \"prompt\": prompt,\n            \"num_inference_steps\": num_inference_steps\n        }\n    )\n\n    data = response.json()\n\n    if data[\"status\"] == \"error\":\n        raise Exception(f\"Error: {data['message']}\")\n\n    if data[\"status\"] == \"success\":\n        return data[\"output\"][0]\n\n    # 3D generation is async - poll for results\n    request_id = data[\"id\"]\n    print(f\"3D generation started... Request ID: {request_id}\")\n    print(f\"ETA: {data.get('eta', 'unknown')} seconds\")\n\n    return poll_3d_result(request_id, api_key)\n\ndef poll_3d_result(request_id, api_key, timeout=600):\n    \"\"\"Poll for 3D generation results.\"\"\"\n    start_time = time.time()\n\n    while time.time() - start_time < timeout:\n        fetch = requests.post(\n            f\"https://modelslab.com/api/v6/3d/fetch/{request_id}\",\n            json={\"key\": api_key}\n        )\n        result = fetch.json()\n\n        if result[\"status\"] == \"success\":\n            return result[\"output\"][0]\n        elif result[\"status\"] == \"failed\":\n            raise Exception(result.get(\"message\", \"Generation failed\"))\n\n        print(f\"Status: processing... ({int(time.time() - start_time)}s elapsed)\")\n        time.sleep(10)\n\n    raise Exception(\"Timeout waiting for 3D generation\")\n\n# Usage\nmodel_url = text_to_3d(\n    \"A medieval sword with ornate handle and detailed engravings\",\n    \"your_api_key\",\n    num_inference_steps=50\n)\nprint(f\"3D model ready: {model_url}\")\n```\n\n## Image to 3D\n\n```python\ndef image_to_3d(image_url, api_key):\n    \"\"\"Convert a 2D image into a 3D model.\n\n    Args:\n        image_url: URL of the 2D image\n        api_key: Your ModelsLab API key\n\n    Returns:\n        URL of the generated 3D model\n    \"\"\"\n    response = requests.post(\n        \"https://model"},{"path":"account-management/SKILL.md","content":"---\nname: modelslab-account-management\ndescription: Manage ModelsLab accounts programmatically — signup, login, token management, profile updates, API key CRUD, and team member management. Uses the Agent Control Plane API with bearer token auth.\n---\n\n# ModelsLab Account Management\n\nManage the full ModelsLab account lifecycle via the Agent Control Plane API — authentication, tokens, profile, API keys, and teams.\n\n## When to Use This Skill\n\n- Sign up or log in to ModelsLab programmatically\n- Create and manage API keys for generation endpoints\n- Update user profile, password, or social links\n- Manage access tokens (list, revoke, switch team accounts)\n- Invite, update, or remove team members\n- Build agent workflows that need account bootstrapping\n\n## Authentication\n\nThe Agent Control Plane uses **bearer tokens** (not API keys). Some endpoints (signup, login, forgot-password) work without a token.\n\n```\nBase URL: https://modelslab.com/api/agents/v1\nAuthorization: Bearer <agent_access_token>\n```\n\n## Auth: Signup & Login\n\n### Sign Up\n\n```python\nimport requests\n\ndef signup(email, password, name=None):\n    \"\"\"Create a new ModelsLab account.\"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/agents/v1/auth/signup\",\n        json={\n            \"email\": email,\n            \"password\": password,\n            \"name\": name or \"\"\n        }\n    )\n    data = response.json()\n    if \"error\" in data:\n        raise Exception(data[\"error\"])\n    return data[\"data\"]  # Contains access_token\n\n# Usage\nresult = signup(\"agent@example.com\", \"securepass123\", \"My Agent\")\ntoken = result[\"access_token\"]\nprint(f\"Signed up! Token: {token}\")\n```\n\n### Log In\n\n```python\ndef login(email, password, token_expiry=\"1_month\"):\n    \"\"\"Log in and get a bearer token.\n\n    Args:\n        token_expiry: \"1_week\", \"1_month\" (default), \"3_months\", \"never\"\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/agents/v1/auth/login\",\n        json={\n            \"email\": email,\n            \"password\": password,\n            \"device_name\": \"my-agent\",\n            \"token_expiry\": token_expiry\n        }\n    )\n    data = response.json()\n    if \"error\" in data:\n        raise Exception(data[\"error\"])\n    return data[\"data\"][\"access_token\"]\n\n# Usage\ntoken = login(\"agent@example.com\", \"securepass123\")\n```\n\n### Logout\n\n```python\ndef logout(token):\n    \"\"\"Revoke current token.\"\"\"\n    requests.post(\n        \"https://modelslab.com/api/agents/v1/auth/logout\",\n        headers={\"Authorization\": f\"Bearer {token}\"}\n    )\n\ndef logout_all(token):\n    \"\"\"Revoke all tokens for this account.\"\"\"\n    requests.post(\n        \"https://modelslab.com/api/agents/v1/auth/logout-all\",\n        headers={\"Authorization\": f\"Bearer {token}\"}\n    )\n```\n\n### Verify Email (Headless)\n\nAfter signup, the user receives a `verification_code` via email. Verify without a browser:\n\n```python\ndef verify_email(verification_code):\n    \"\"\"Verify email with the code from the verification email.\n\n    Returns an access_token an"},{"path":"audio-generation/SKILL.md","content":"---\nname: modelslab-audio-generation\ndescription: Generate speech, music, and sound effects using ModelsLab's v7 Voice API. Supports text-to-speech, speech-to-text, speech-to-speech, music generation, sound effects, dubbing, song extension, and song inpainting via ElevenLabs and Inworld models.\n---\n\n# ModelsLab Audio Generation\n\nGenerate high-quality audio including speech, music, voice conversion, sound effects, and dubbing using AI.\n\n## When to Use This Skill\n\n- Convert text to natural-sounding speech (TTS)\n- Transcribe speech to text\n- Transform voice characteristics (speech-to-speech)\n- Generate music from text prompts\n- Create sound effects\n- Dub audio into different languages\n- Extend or inpaint songs\n- Build voice assistants or audiobooks\n\n## Available APIs (v7)\n\n### Voice Endpoints\n- **Text to Speech**: `POST https://modelslab.com/api/v7/voice/text-to-speech`\n- **Speech to Text**: `POST https://modelslab.com/api/v7/voice/speech-to-text`\n- **Speech to Speech**: `POST https://modelslab.com/api/v7/voice/speech-to-speech`\n- **Music Generation**: `POST https://modelslab.com/api/v7/voice/music-gen`\n- **Sound Generation**: `POST https://modelslab.com/api/v7/voice/sound-generation`\n- **Create Dubbing**: `POST https://modelslab.com/api/v7/voice/create-dubbing`\n- **Song Extender**: `POST https://modelslab.com/api/v7/voice/song-extender`\n- **Song Inpaint**: `POST https://modelslab.com/api/v7/voice/song-inpaint`\n- **Fetch Result**: `POST https://modelslab.com/api/v7/voice/fetch/{id}`\n\n> **Note**: v6 endpoints (`/api/v6/voice/text_to_speech`, etc.) still work but v7 is the current version. Parameter names have changed in v7 (e.g., `text` is now `prompt`, `audio` is now `init_audio`).\n\n## Discovering Audio Models\n\n```bash\n# Search audio/voice models\nmodelslab models search --feature audio_gen\n\n# Search by provider\nmodelslab models search --search \"eleven\"\n\n# Get model details\nmodelslab models detail --id eleven_multilingual_v2\n```\n\n## Audio Model IDs\n\n| model_id | Name | Use With |\n|----------|------|----------|\n| `eleven_multilingual_v2` | ElevenLabs Multilingual v2 | text-to-speech |\n| `eleven_english_sts_v2` | ElevenLabs Voice Changer | speech-to-speech |\n| `scribe_v1` | ElevenLabs Scribe | speech-to-text |\n| `eleven_sound_effect` | ElevenLabs Sound Effects | sound-generation |\n| `music_v1` | ElevenLabs Music | music-gen |\n| `inworld-tts-1` | Inworld TTS | text-to-speech |\n\n## Text to Speech\n\n```python\nimport requests\nimport time\n\ndef text_to_speech(text, api_key, voice_id=\"21m00Tcm4TlvDq8ikWAM\", model_id=\"eleven_multilingual_v2\"):\n    \"\"\"Convert text to speech.\n\n    Args:\n        text: The text to convert to speech\n        api_key: Your ModelsLab API key\n        voice_id: ElevenLabs voice ID (see Available Voices below)\n        model_id: TTS model to use\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v7/voice/text-to-speech\",\n        json={\n            \"key\": api_key,\n            \"prompt\": text,             # v7 uses \"prom"},{"path":"billing-subscriptions/SKILL.md","content":"---\nname: modelslab-billing-subscriptions\ndescription: Manage ModelsLab billing, wallet balance, payment methods, subscriptions, invoices, and coupons programmatically via the Agent Control Plane API.\n---\n\n# ModelsLab Billing & Subscriptions\n\nManage billing, wallet funding, payment methods, subscriptions, and coupons via the Agent Control Plane API.\n\n## When to Use This Skill\n\n- Check wallet balance and fund it\n- Set up auto-recharge for wallets\n- Manage payment methods (add, set default, remove)\n- Create payment links for human-assisted checkout\n- Confirm Stripe Checkout sessions (wallet funding or subscriptions)\n- View and download invoices\n- Create, upgrade, pause, or resume subscriptions\n- Validate and redeem coupons\n- Update billing information (address, tax ID)\n\n## Authentication\n\nAll billing endpoints require a bearer token.\n\n```\nBase URL: https://modelslab.com/api/agents/v1\nAuthorization: Bearer <agent_access_token>\n```\n\nGet a token via the `modelslab-account-management` skill or `POST /auth/login`.\n\n## Helper\n\n```python\nimport requests\n\nBASE = \"https://modelslab.com/api/agents/v1\"\n\ndef headers(token):\n    return {\"Authorization\": f\"Bearer {token}\"}\n```\n\n## Billing Overview\n\n```python\ndef get_billing_overview(token):\n    \"\"\"Get billing overview — balance, active subscriptions, recent charges.\"\"\"\n    resp = requests.get(f\"{BASE}/billing/overview\", headers=headers(token))\n    return resp.json()[\"data\"]\n\n# Usage\noverview = get_billing_overview(token)\nprint(f\"Wallet balance: ${overview.get('wallet_balance', 0)}\")\n```\n\n## Three Payment Paths\n\nModelsLab supports three ways for agents to handle payments:\n\n| Path | Best For | Flow |\n|------|----------|------|\n| **Headless** | Autonomous agents with card data | `GET /billing/stripe-config` -> tokenize via Stripe API -> pass `payment_method_id` to fund/subscribe |\n| **Setup Intent** | Save a card for reuse without immediate charge | `POST /billing/setup-intent` -> confirm with Stripe -> reuse `payment_method_id` for future fund/subscribe |\n| **Human-Assisted** | Agents that cannot handle card data directly | `POST /billing/payment-link` -> forward URL to human -> human pays on Stripe Checkout -> poll `confirm-checkout` |\n\n## Stripe Config\n\nFetch the Stripe publishable key dynamically instead of hardcoding it. Useful for agents that need to tokenize cards client-side.\n\n```python\ndef get_stripe_config(token):\n    \"\"\"Get the Stripe publishable key for client-side card tokenization.\n\n    Returns:\n        publishable_key: Stripe publishable key (pk_...)\n        instructions: Usage guidance from the API\n    \"\"\"\n    resp = requests.get(f\"{BASE}/billing/stripe-config\", headers=headers(token))\n    return resp.json()[\"data\"]\n\n# Usage\nconfig = get_stripe_config(token)\nstripe_pk = config[\"publishable_key\"]  # e.g., \"pk_live_...\"\n```\n\n> **Tip:** The publishable key is safe to embed in agent code — it can only create tokens, never charge directly. You can either fetch it dynamically via this endpoint or use the "},{"path":"chat-generation/SKILL.md","content":"---\nname: modelslab-chat-generation\ndescription: Chat with LLM models using ModelsLab's OpenAI-compatible Chat Completions API. Supports 60+ models including DeepSeek R1, Meta Llama, Google Gemini, Qwen, and Mistral with streaming, function calling, and structured outputs.\n---\n\n# ModelsLab Chat/LLM Generation\n\nSend chat completions to 60+ LLM models through a single OpenAI-compatible endpoint.\n\n## When to Use This Skill\n\n- Chat with AI models (DeepSeek, Llama, Gemini, Qwen, Mistral)\n- Build conversational AI applications\n- Generate text completions with system prompts\n- Use function/tool calling with LLMs\n- Stream responses for real-time output\n- Get structured JSON responses\n\n## API Endpoint\n\n**Chat Completions**: `POST https://modelslab.com/api/v7/llm/chat/completions`\n\nThe endpoint follows the OpenAI chat completions format, making it easy to switch from OpenAI or use the OpenAI SDK.\n\n## Quick Start\n\n```python\nimport requests\n\ndef chat(message, api_key, model=\"meta-llama-3-8B-instruct\"):\n    \"\"\"Send a chat completion request.\n\n    Args:\n        message: The user message\n        api_key: Your ModelsLab API key\n        model: LLM model ID (use modelslab models search --feature llmaster to find models)\n    \"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v7/llm/chat/completions\",\n        json={\n            \"key\": api_key,\n            \"model_id\": model,\n            \"messages\": [\n                {\"role\": \"user\", \"content\": message}\n            ],\n            \"max_tokens\": 200,\n            \"temperature\": 0.7\n        }\n    )\n\n    data = response.json()\n\n    if \"choices\" in data:\n        return data[\"choices\"][0][\"message\"][\"content\"]\n    else:\n        raise Exception(f\"Error: {data.get('message', 'Unknown error')}\")\n\n# Usage\nreply = chat(\n    \"Explain quantum computing in simple terms.\",\n    \"your_api_key\"\n)\nprint(reply)\n```\n\n## With System Prompt\n\n```python\ndef chat_with_system(system_prompt, message, api_key, model=\"meta-llama-3-8B-instruct\"):\n    \"\"\"Chat with a system prompt for role/behavior control.\"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v7/llm/chat/completions\",\n        json={\n            \"key\": api_key,\n            \"model_id\": model,\n            \"messages\": [\n                {\"role\": \"system\", \"content\": system_prompt},\n                {\"role\": \"user\", \"content\": message}\n            ],\n            \"max_tokens\": 500,\n            \"temperature\": 0.7\n        }\n    )\n\n    data = response.json()\n    if \"choices\" in data:\n        return data[\"choices\"][0][\"message\"][\"content\"]\n\n# Usage\nreply = chat_with_system(\n    \"You are a Python expert. Give concise code examples.\",\n    \"How do I read a CSV file?\",\n    \"your_api_key\"\n)\n```\n\n## Multi-Turn Conversation\n\n```python\ndef conversation(messages, api_key, model=\"meta-llama-3-8B-instruct\"):\n    \"\"\"Send a multi-turn conversation.\"\"\"\n    response = requests.post(\n        \"https://modelslab.com/api/v7/llm/chat/completions\",\n        json={\n            \"key\": ap"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1508,"uniquenessScore":34,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-12T02:32:36.252Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-12T02:32:36.252Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-14T06:38:39.931Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}