{
  "catalog_version": "2026-09-26.1",
  "updated": "2026-09-26",
  "base_url": "https://dashboard.alphanetplus.com",
  "auth": {
    "header": "Authorization: Bearer <project API key>",
    "key_note": "Sign in to the gateway, open the project, and copy its API key. The same key lists its models at GET /v1/models."
  },
  "price": "$0.01 per call",
  "limits": {
    "max_upload_bytes": 10485760,
    "references_per_call": {
      "min": 1,
      "max": 4
    },
    "result_url_ttl_seconds": 900
  },
  "aspects": [
    {
      "value": "1:1",
      "size": "1024 × 1024"
    },
    {
      "value": "3:4",
      "size": "768 × 1024"
    },
    {
      "value": "4:3",
      "size": "1024 × 768"
    },
    {
      "value": "2:3",
      "size": "768 × 1152"
    },
    {
      "value": "3:2",
      "size": "1152 × 768"
    },
    {
      "value": "16:9",
      "size": "1344 × 768"
    },
    {
      "value": "9:16",
      "size": "768 × 1344"
    }
  ],
  "flow": [
    {
      "step": 1,
      "method": "POST",
      "path": "/v1/flux/uploads",
      "title": "Open an upload ticket",
      "detail": "One ticket per reference image. The response carries the URL to PUT the bytes to, the file id you submit, and the byte ceiling."
    },
    {
      "step": 2,
      "method": "PUT",
      "path": "{upload_url}",
      "title": "Upload the bytes",
      "detail": "Send the file itself to the signed URL, with the headers from the ticket. Nothing else goes through our API: the bytes go straight to storage."
    },
    {
      "step": 3,
      "method": "POST",
      "path": "/v1/tasks/alphanet-flux",
      "title": "Submit the task",
      "detail": "The model id and the file ids in order. Always send an Idempotency-Key: the same key and body return the same task, a different body under the same key is refused with 409."
    },
    {
      "step": 4,
      "method": "GET",
      "path": "/v1/tasks/{task_id}",
      "title": "Poll, then fetch the result",
      "detail": "Poll until the status is terminal, then read /v1/tasks/{task_id}/result for the signed URLs and the sha256 of each artifact."
    }
  ],
  "models": [
    {
      "id": "flux-klein",
      "label": "Generative edit, upscale and restore",
      "summary": "The general-purpose editor: your prompt decides what happens, and the output is the size you ask for.",
      "capability": "generative_repaint",
      "inputs": {
        "min": 1,
        "max": 4,
        "slots": [
          "the image to edit"
        ]
      },
      "params": [
        {
          "name": "prompt",
          "type": "string",
          "required": true,
          "note": "What should change. The only model here that reads your own words."
        },
        {
          "name": "width",
          "type": "integer",
          "default": "1024",
          "note": "Output width: a multiple of 16, at most 1536 px."
        },
        {
          "name": "height",
          "type": "integer",
          "default": "1024",
          "note": "Output height, under the same rules."
        },
        {
          "name": "num_inference_steps",
          "type": "integer",
          "default": "4",
          "note": "Four steps unless you ask for more; more steps refine detail and take longer."
        },
        {
          "name": "seed",
          "type": "integer",
          "note": "Same seed and body reproduces the same render."
        },
        {
          "name": "max_sequence_length",
          "type": "integer"
        },
        {
          "name": "output_format",
          "type": "string",
          "values": "png | webp"
        },
        {
          "name": "output_quality",
          "type": "integer"
        }
      ],
      "refuses": [],
      "output": "PNG or WebP at the width and height you sent; 1–4 references may be combined.",
      "latency": "~16 s end to end for a 1152 × 1536 render, 6.4 s of it inference (measured 2026-09-26); the rest is queueing and the result upload",
      "limits": [
        "It is a generative re-render: faces and small text can shift. Review the result at 100% before publishing.",
        "It cannot add detail that was never captured with certainty — an upscale reconstructs plausible texture, not the original pixels."
      ],
      "submit_body_example": {
        "model": "flux-klein",
        "image_ids": [
          "<file_id>"
        ],
        "prompt": "Restore realistic detail, texture and sharpness at 2x the size while keeping the composition identical. Do not add objects and do not change the framing.",
        "width": 1152,
        "height": 1536,
        "num_inference_steps": 8,
        "seed": 42,
        "output_format": "png"
      },
      "price": "$0.01 per call",
      "try_it": "/image-upscaler",
      "cases": [],
      "verified": "2026-09-26 (public gateway)"
    },
    {
      "id": "pixrestore-s",
      "label": "Detail restore",
      "summary": "Renders a sharper, cleaner version of an image at its own size. No prompt, no knobs beyond steps.",
      "capability": "detail_restore",
      "inputs": {
        "min": 1,
        "max": 1,
        "slots": [
          "the image"
        ]
      },
      "params": [
        {
          "name": "num_inference_steps",
          "type": "integer",
          "values": "1–4",
          "default": "1",
          "note": "One pass is the service default, and on this model one pass measured better than four on 2026-09-17 — more steps is not more detail here."
        },
        {
          "name": "seed",
          "type": "integer"
        }
      ],
      "refuses": [
        "width",
        "height",
        "max_sequence_length",
        "output_format",
        "output_quality"
      ],
      "output": "PNG at the input size.",
      "latency": "~3.5 s for a 3131 × 1549 frame (measured 2026-09-17, end to end)",
      "limits": [
        "The result is \"clearer\", not \"faithful\": detail is generated, so fine text and small patterns can change. It is not a lossless enlarger.",
        "It does not resize: send the size you want to keep, or upscale separately."
      ],
      "submit_body_example": {
        "model": "pixrestore-s",
        "image_ids": [
          "<file_id>"
        ],
        "num_inference_steps": 1,
        "seed": 42
      },
      "price": "$0.01 per call",
      "try_it": null,
      "cases": [],
      "verified": "2026-09-17 (public gateway, 8/8 with the idempotency pair)"
    },
    {
      "id": "cutout-fast",
      "label": "Background removal",
      "summary": "Cuts the subject out and answers a PNG with an alpha channel at the input size.",
      "capability": "tool_cutout",
      "inputs": {
        "min": 1,
        "max": 1,
        "slots": [
          "the photo"
        ]
      },
      "params": [
        {
          "name": "bg_color",
          "type": "string",
          "note": "Fill the removed background with a colour instead of leaving it transparent."
        },
        {
          "name": "bg_model",
          "type": "string",
          "note": "Which matting model the service picks (isnet, birefnet or u2net family)."
        },
        {
          "name": "alpha_matting",
          "type": "string",
          "note": "Softer edges on hair and fur, at a little more time."
        }
      ],
      "refuses": [
        "width",
        "height",
        "max_sequence_length",
        "output_format",
        "output_quality"
      ],
      "output": "PNG with transparency, at the input size — 768 × 1024 in, 768 × 1024 out.",
      "latency": "~5 s end to end, 0.8 s of it inference (measured 2026-09-26)",
      "limits": [
        "Fine hair, glass and motion blur keep some background; a see-through subject cannot be cut cleanly.",
        "The cut is the whole frame. There is no per-object selection: one subject per call."
      ],
      "submit_body_example": {
        "model": "cutout-fast",
        "image_ids": [
          "<file_id>"
        ]
      },
      "price": "$0.01 per call",
      "try_it": "/remove-background",
      "cases": [
        "cutout-teapot"
      ],
      "verified": "2026-09-26 (public gateway)"
    },
    {
      "id": "erase-quality",
      "label": "Generative erase",
      "summary": "Names what should go; the model removes it and rebuilds the surface underneath.",
      "capability": "tool_erase",
      "inputs": {
        "min": 1,
        "max": 1,
        "slots": [
          "the photo"
        ]
      },
      "params": [
        {
          "name": "prompt",
          "type": "string",
          "required": true,
          "note": "The object or mark to remove."
        },
        {
          "name": "num_inference_steps",
          "type": "integer",
          "values": "4–20",
          "default": "8"
        },
        {
          "name": "seed",
          "type": "integer"
        }
      ],
      "refuses": [
        "width",
        "height",
        "max_sequence_length",
        "output_format",
        "output_quality"
      ],
      "output": "PNG at a fixed 1024 × 1024, whatever the input size was.",
      "latency": "~54 s end to end, 50 s of it inference (measured 2026-09-22)",
      "limits": [
        "The whole frame is re-rendered at 1024², so a larger original comes back at that size and fine text elsewhere can drift.",
        "It removes what you name; it does not understand \"remove the person but keep the shadow\"."
      ],
      "submit_body_example": {
        "model": "erase-quality",
        "image_ids": [
          "<file_id>"
        ],
        "prompt": "Remove the spoon from the table and rebuild the wooden surface behind it; keep the mug, the napkin and the lighting exactly as they are.",
        "num_inference_steps": 8,
        "seed": 42
      },
      "price": "$0.01 per call",
      "try_it": "/erase-object",
      "cases": [
        "erase-spoon"
      ],
      "verified": "2026-09-22 (public gateway, 8/8)"
    },
    {
      "id": "vectorize-fast",
      "label": "Image to SVG",
      "summary": "Traces a bitmap into real vector paths and answers an SVG — so it scales to any size without blurring.",
      "capability": "tool_vectorize",
      "inputs": {
        "min": 1,
        "max": 1,
        "slots": [
          "the bitmap"
        ]
      },
      "params": [
        {
          "name": "preset",
          "type": "string",
          "values": "logo | illustration | photo",
          "default": "logo",
          "note": "A fixed parameter set on the service, not free text."
        },
        {
          "name": "max_edge",
          "type": "integer",
          "values": "256–2048",
          "default": "1024",
          "note": "Long edge the trace runs at; larger input is downscaled to it."
        },
        {
          "name": "colors",
          "type": "integer",
          "values": "2–64"
        },
        {
          "name": "filter_speckle",
          "type": "integer",
          "values": "0–32",
          "note": "Drops specks smaller than this many pixels."
        }
      ],
      "refuses": [
        "width",
        "height",
        "max_sequence_length",
        "output_format",
        "output_quality"
      ],
      "output": "image/svg+xml. The SVG declares its own width and height, so the JSON result reports width/height as null.",
      "latency": "~7 s end to end, 0.4 s of it tracing (measured 2026-09-22)",
      "limits": [
        "A photograph comes back posterised: the photo preset limits the palette to 16 colours before tracing.",
        "The output is paths, not an embedded bitmap — expect a small file for a logo and a large one for a picture."
      ],
      "submit_body_example": {
        "model": "vectorize-fast",
        "image_ids": [
          "<file_id>"
        ],
        "preset": "logo"
      },
      "price": "$0.01 per call",
      "try_it": "/image-to-svg",
      "cases": [
        "vectorize-badge"
      ],
      "verified": "2026-09-22 (public gateway, 8/8)"
    },
    {
      "id": "tryon-quality",
      "label": "Virtual try-on",
      "summary": "Puts the garment from one photo onto the person in another. Two references, in order, and no prompt.",
      "capability": "tool_tryon",
      "inputs": {
        "min": 2,
        "max": 2,
        "slots": [
          "person",
          "garment"
        ]
      },
      "params": [
        {
          "name": "garment_type",
          "type": "string",
          "values": "top | bottom | dress | outfit",
          "default": "top",
          "note": "Which part of the outfit the reference replaces. Omitted, the reference is read as a top."
        },
        {
          "name": "aspect",
          "type": "string",
          "values": "1:1 | 3:4 | 4:3 | 2:3 | 3:2 | 16:9 | 9:16",
          "note": "Optional. Omitted, the output follows the person photo’s shape — a 3:4 portrait comes back 768 × 1024."
        },
        {
          "name": "seed",
          "type": "integer"
        }
      ],
      "refuses": [
        "prompt",
        "width",
        "height",
        "num_inference_steps",
        "max_sequence_length",
        "output_format",
        "output_quality"
      ],
      "output": "PNG shaped like the person photo (3:4 → 768 × 1024). Face, hair, pose, other clothing and background are asked to stay identical.",
      "latency": "~69 s end to end, 59 s of it inference (measured 2026-09-26)",
      "limits": [
        "One garment per call: the reference is read as a single piece, so a top and a bottom need two calls.",
        "The order of image_ids is the meaning — person first, garment second. Swapping them changes the result, not the error.",
        "Layered outfits, heavy shadows across the garment and unusual poses are the hard cases."
      ],
      "submit_body_example": {
        "model": "tryon-quality",
        "image_ids": [
          "<person_file_id>",
          "<garment_file_id>"
        ],
        "garment_type": "top"
      },
      "price": "$0.01 per call",
      "try_it": "/virtual-try-on",
      "cases": [
        "tryon-top"
      ],
      "verified": "2026-09-26 (public gateway, re-measured); the 10/10 pass including the idempotency pair was 2026-09-25"
    },
    {
      "id": "interior-quality",
      "label": "Interior render",
      "summary": "Turns an empty or unfinished room into a furnished render in a named style, keeping the architecture where it is.",
      "capability": "tool_interior",
      "inputs": {
        "min": 1,
        "max": 2,
        "slots": [
          "room",
          "style reference (optional)"
        ]
      },
      "params": [
        {
          "name": "style",
          "type": "string",
          "values": "nordic | cream | japandi | chinese | industrial | french",
          "default": "nordic",
          "note": "Each style is a fixed recipe of materials, furniture and lighting."
        },
        {
          "name": "room_type",
          "type": "string",
          "values": "living_room | bedroom | dining_room | study | kitchen | bathroom | kids_room | balcony",
          "default": "living_room"
        },
        {
          "name": "extra",
          "type": "string",
          "note": "Up to 120 characters of extra brief, folded into the fixed instruction. Longer is refused: it would start to override the parts that hold the room in place."
        },
        {
          "name": "aspect",
          "type": "string",
          "values": "1:1 | 3:4 | 4:3 | 2:3 | 3:2 | 16:9 | 9:16",
          "note": "Optional. Omitted, the output follows the room photo’s shape — 3:2 comes back 1152 × 768."
        },
        {
          "name": "seed",
          "type": "integer"
        }
      ],
      "refuses": [
        "prompt",
        "width",
        "height",
        "num_inference_steps",
        "max_sequence_length",
        "output_format",
        "output_quality"
      ],
      "output": "PNG shaped like the room photo (3:2 → 1152 × 768), with walls, windows, doors, ceiling line and camera angle held.",
      "latency": "~59 s of inference (measured 2026-09-25)",
      "limits": [
        "Start from the emptiest frame you have: a room that is already furnished comes back redesigned rather than built on.",
        "The second reference steers palette and materials only — it cannot add a wall or move a window.",
        "It is a visualisation, not a measured plan: sockets, floor coverings and furniture proportions can differ from the building."
      ],
      "submit_body_example": {
        "model": "interior-quality",
        "image_ids": [
          "<room_file_id>"
        ],
        "style": "nordic",
        "room_type": "living_room",
        "extra": "light oak flooring, a linen sofa, a round wooden coffee table, a woven rug, a floor lamp and green plants"
      },
      "price": "$0.01 per call",
      "try_it": "/interior-design",
      "cases": [
        "interior-nordic",
        "interior-japandi-ref"
      ],
      "verified": "2026-09-25 (public gateway, 8/8)"
    },
    {
      "id": "retouch-quality",
      "label": "Portrait retouch",
      "summary": "Cleans up a portrait — skin, under-eyes, eyes, stray hairs — without changing the face.",
      "capability": "tool_retouch",
      "inputs": {
        "min": 1,
        "max": 1,
        "slots": [
          "portrait"
        ]
      },
      "params": [
        {
          "name": "level",
          "type": "string",
          "values": "light | natural | strong",
          "default": "natural"
        },
        {
          "name": "aspect",
          "type": "string",
          "values": "1:1 | 3:4 | 4:3 | 2:3 | 3:2 | 16:9 | 9:16",
          "note": "Optional. Omitted, the output follows the portrait’s shape (fallback 1:1)."
        },
        {
          "name": "seed",
          "type": "integer"
        }
      ],
      "refuses": [
        "prompt",
        "width",
        "height",
        "num_inference_steps",
        "max_sequence_length",
        "output_format",
        "output_quality"
      ],
      "output": "PNG shaped like the portrait, with skin grain kept.",
      "latency": "~79 s end to end, 61 s of it inference (measured 2026-09-25)",
      "limits": [
        "It will not slim a face, widen the eyes or change a hairstyle: that is the instruction, not a setting.",
        "It does not add makeup — that is the separate virtual-makeup model.",
        "A heavy filter look is refused on purpose; the result keeps visible texture."
      ],
      "submit_body_example": {
        "model": "retouch-quality",
        "image_ids": [
          "<portrait_file_id>"
        ],
        "level": "natural"
      },
      "price": "$0.01 per call",
      "try_it": "/portrait-retouch",
      "cases": [
        "retouch-natural"
      ],
      "verified": "2026-09-25 (public gateway, 8/8)"
    },
    {
      "id": "makeup-quality",
      "label": "Virtual makeup",
      "summary": "Applies a named makeup look to a face, optionally matched from a reference photo.",
      "capability": "tool_makeup",
      "inputs": {
        "min": 1,
        "max": 2,
        "slots": [
          "portrait",
          "makeup reference (optional)"
        ]
      },
      "params": [
        {
          "name": "look",
          "type": "string",
          "values": "daily | korean | glam | bridal | latte | retro",
          "default": "daily",
          "note": "A fixed recipe of base, contour, brows, eyeshadow, liner, lashes and lip."
        },
        {
          "name": "intensity",
          "type": "string",
          "values": "light | medium | strong",
          "default": "medium"
        },
        {
          "name": "aspect",
          "type": "string",
          "values": "1:1 | 3:4 | 4:3 | 2:3 | 3:2 | 16:9 | 9:16",
          "note": "Optional. Omitted, the output follows the portrait’s shape (fallback 1:1)."
        },
        {
          "name": "seed",
          "type": "integer"
        }
      ],
      "refuses": [
        "prompt",
        "width",
        "height",
        "num_inference_steps",
        "max_sequence_length",
        "output_format",
        "output_quality"
      ],
      "output": "PNG shaped like the portrait. Identity, expression, hair, clothing, framing and lighting are asked to stay as they are.",
      "latency": "~62 s of inference (measured 2026-09-25)",
      "limits": [
        "A look is a recipe, not a brand shade: use it to compare directions, not to promise an exact product.",
        "The palette is matched to this person’s undertone and the original lighting, so the same reference gives a different result on another photo."
      ],
      "submit_body_example": {
        "model": "makeup-quality",
        "image_ids": [
          "<portrait_file_id>"
        ],
        "look": "korean",
        "intensity": "medium"
      },
      "price": "$0.01 per call",
      "try_it": "/virtual-makeup",
      "cases": [
        "makeup-korean",
        "makeup-glam-ref"
      ],
      "verified": "2026-09-25 (public gateway, 8/8)"
    }
  ]
}
