# Move an image integration to SeedRouter

By SeedRouter · Published 2026-09-21 · Updated 2026-09-21

An image API migration to SeedRouter requires checking the request and response contract, not just replacing the API key and base URL. GPT Image 2 uses familiar image-generation fields, but submission returns a task ID. Your application must save that ID, poll for completion, and read the finished image URLs.

The smallest useful migration is one text-to-image request from server-side code. Get that working before moving reference edits, masks, or a larger batch. Keep the existing integration available until the new path passes the same acceptance checks.

## Which assumptions need to change?

Find the code that turns an image request into a usable file. It may currently expect an image in the initial response, decode a base64 field, or use a multipart upload. Those assumptions must be checked individually against the [SeedRouter GPT Image 2 reference](https://seedrouter.ai/docs/gpt-image-2).

| Existing assumption                        | SeedRouter contract                        | Application change                  |
| ------------------------------------------ | ------------------------------------------ | ----------------------------------- |
| Submission returns the finished image      | Submission returns a task reference        | Save `id` before waiting for output |
| Output is in the submission's `data` array | Completed task images are in `output.data` | Read results after completion       |
| The client decodes `b64_json`              | Images are returned as hosted URLs         | Download the returned URLs          |
| Editing uploads file bytes                 | References use `images` URL objects        | Make input images accessible by URL |
| A separate edits path selects editing      | `images` and `mask` select the operation   | Use the public generations endpoint |
| A client timeout means the image failed    | The task may still be processing           | Resume checking the saved ID        |

This is why a synchronous Images SDK call is not a drop-in replacement even if it accepts a configurable base URL. Keep the model settings you still need, but adapt the application code that waits for and consumes the result.

## Map the request fields before moving code

Start with `model`, `prompt`, `size`, `quality`, and `n`. Use `gpt-image-2` as the model ID. Send explicit dimensions such as `1024x1024` or use `auto`; do not carry over a separate `resolution` field or an aspect-ratio string as the size.

SeedRouter's [OpenAPI document](https://seedrouter.ai/docs/gpt-image-2.openapi.json) is a useful review companion. Compare the fields your application actually sends, including values supplied by an SDK, rather than checking only the arguments visible at the call site. Unknown fields are rejected.

For this model, `style`, `response_format`, and configurable `input_fidelity` are not accepted request fields. Remove those assumptions rather than hiding them inside a generic options object. The request also does not support `stream` or `partial_images`; the task status is how this integration reports progress.

Output settings have dependencies. If you request transparency, select PNG. Send `output_compression` only for JPEG, not PNG. A zero compression value is valid, so avoid a truthiness check that replaces it with a default. These are small details that a successful basic request will not exercise.

## Replace the synchronous response assumption

The following Node.js example submits one request and prints its task ID. Set `SEEDROUTER_API_KEY` on the server; never place the key in browser code or a public environment variable.

```javascript
const response = await fetch('https://api.seedrouter.ai/v1/images/generations', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.SEEDROUTER_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    model: 'gpt-image-2',
    prompt: 'A cobalt-blue ceramic mug on a pale gray tabletop.',
    size: '1024x1024',
    quality: 'low',
    n: 1,
  }),
  signal: AbortSignal.timeout(60000),
});
const task = await response.json();
if (!response.ok) {
  // Preserve a task reference if one accompanies an uncertain submission.
  if (typeof task.id === 'string') console.log('Task reference:', task.id);
  throw new Error(`Submission needs review: HTTP ${response.status}`);
}
if (typeof task.id !== 'string' || !task.id) throw new Error('Missing task ID.');
console.log(task.id); // Persist this ID with your application's image record.
```

Printing the ID is enough for a manual smoke test. In an application, store it before returning control to the user. Your image record can then remain pending while the user navigates elsewhere, and a later check can recover the result.

Use `GET https://api.seedrouter.ai/v1/tasks/{id}` with the same authorization header to check progress. On `completed`, read `output.data[].url`. On `failed`, handle the documented error and show an appropriate failure state. For a runnable example that persists progress, see [batch submission and polling](https://seedrouter.ai/blog/gpt-image-2-batch-generation).

Do not attach the API key to the image-download request. Authorization belongs on the task API call, not on a separate fetch of a returned asset URL.

## Move references and masks to URL inputs

An existing local-file workflow needs an extra preparation step: make the reference image available at an accessible HTTP(S) URL you control. Pass it as `images: [{"image_url": "https://example.com/reference.png"}]`, replacing that address with your own. Do not send a file path, `blob:` URL, base64 data URL, or Files ID.

Check that the URL works without your browser's login cookies. A URL that opens only in your signed-in session is not a usable reference for this request. Keep the image accessible while the task is processing; do not revoke access immediately after submission.

A mask uses `mask: {"image_url": "https://example.com/mask.png"}` and requires reference images. It must match the dimensions of the first reference image. Review [all media-input constraints](https://seedrouter.ai/docs/gpt-image-2#media-inputs) before moving an existing editing flow, particularly file formats and file sizes.

## What should the migration acceptance test cover?

Test the behavior your application relies on, including interruption. One successful image proves only that one request worked. It does not prove that your pending state survives a refresh or that a download failure will avoid duplicate generation.

* Submit a text-only request and store the returned ID before polling.
* Stop polling, restart it with that same ID, and verify no additional POST occurs.
* Handle `processing`, `completed`, and `failed` as distinct states.
* Download a completed image without sending the API authorization header.
* Check a reference edit with an accessible URL, then check the failure handling for an inaccessible one.
* Validate optional fields, including compression set to zero, using the published schema.
* Confirm that account charges are read from usage history, not an invented task-response cost field.

Use mocked responses for repeatable failure and timeout tests. Make a small, deliberate live test only after those checks pass; real generations consume balance. If the submission result is uncertain, investigate before retrying it. A local exception is not proof that no task was accepted.

## Frequently asked questions

### Can I keep my existing prompts?

Yes, as a starting point, provided they meet the request constraints. Keep a few representative prompts for comparison, but do not expect identical images from repeated generations.

### Do I need a new client library?

Not for the examples here. Standard HTTP requests are sufficient. Whatever client you choose must handle task submission and polling instead of expecting a finished image immediately.

### Where do I find the final cost?

In [account usage history](https://seedrouter.ai/usage). A completed task can include token usage, but its public response has no dollar-cost field. The [pricing guide](https://seedrouter.ai/blog/gpt-image-2-pricing) covers estimates.

## Finish the migration at the application boundary

An image API migration is complete when the application handles the whole result lifecycle: accepted task, pending state, finished output, download, and failure. Keep the first change small, test the interruption cases, and move the remaining requests only after their input and output assumptions have been checked.
