ToolsAPI provides asynchronous OpenAI-backed image generation for the web interface, authenticated API clients, approved integrations and, when enabled, a restricted guest page.
The same job and status model is used across these entry points. A client can keep polling the returned status URL or request a completion notification and leave the generation running in the background.
Authenticated users with image-generation access can use /admin/openai/images.
The page supports prompt generation, multiple numbered reference images, custom output sizing, optional reference downscaling, removal of selected reference images, live queued progress, structured safety-rejection details, automatic reject retry and completion notifications.
When the signed-in user has an active Tools push destination, GUI image jobs use push as the default completion notification. Android app targets are preferred; browser push is used as the fallback when no active Android target exists. A successful result links directly to the generated image when that URL is available. Rejected and failed jobs use the same terminal push path with matching status text.
Reference images are addressed as {1}, {2}, {3} and so on. Removing a selected file recalculates the remaining reference numbers before submission.
Provider safety rejects are terminal image-generation results rather than generic queue crashes. When available, Tools exposes structured fields such as:
failure_typeerror_codeerror_typerequest_idmoderation_stagemoderation_categoriesrejectionIf automatic retry is enabled, Tools performs one prompt-adjustment request using the original prompt and the structured rejection details. Harmless intent, composition and reference placeholders are preserved where possible. The adjusted prompt is then sent to the image generator once.
The retry path is limited to one adjusted image attempt to avoid loops.
The web progress flow is:
Queued -> Prepare -> Generate -> Retry -> Prepare -> Generate -> Store -> Done
The Retry stage is yellow while the prompt is being adjusted, green when the adjusted retry path succeeds and red when the retry ultimately fails.
Start a generation:
POST /api/ai/openai/images
Read status:
GET /api/ai/openai/images/{sessionId}
New image-specific API tokens should use the scope ai.image.generate. Compatible trusted AI and StorageAPI image-generation scopes can also be accepted according to the account policy.
Image-generation access can be granted through an accepted API token, an account permission or an eligible paid account. GUI, API, X-bot and guest entry points have independent feature policies.
Example request:
{
"prompt": "Create a cinematic landscape using {1} as the reference.",
"model": "gpt-image-1",
"size": "1536x1024",
"quality": "high",
"retry_on_reject": true,
"notify_methods": ["callback"],
"callback_id": 12
}
The API has its own default for retry_on_reject; it does not inherit the web-page default. An explicit value overrides the feature default only when request-level override is enabled for that feature.
A successful start returns HTTP 202 with a job/session ID and status_url. The original HTTP connection does not need to stay open while generation runs.
Authenticated API generation can request one or more allowed methods:
emailsmscallbackExample:
{
"notify_methods": ["email", "sms"]
}
The boolean convenience fields notify_email, notify_sms and notify_callback are also accepted.
Email uses the address stored on the authenticated account. SMS uses the mobile number stored on the account. Callback delivery requires a previously registered callback ID. The authenticated web generator additionally uses the user's existing Tools push destination by default; push registration and transport selection remain managed through the shared account-owned push settings.
Notifications can be sent after completion, rejection or failure.
Callbacks are registered before they can be attached to an image job. A generation request cannot submit an arbitrary callback URL directly.
List registrations:
GET /api/ai/openai/image-callbacks
Register:
POST /api/ai/openai/image-callbacks
{
"name": "My image receiver",
"url": "https://example.com/tools/image-callback",
"events": [
"image_generation.completed",
"image_generation.rejected",
"image_generation.failed"
]
}
The create response includes a signing_secret. The secret is shown only when the callback is created or explicitly rotated.
Update:
PATCH /api/ai/openai/image-callbacks/{callbackId}
Delete:
DELETE /api/ai/openai/image-callbacks/{callbackId}
Rotate signing secret:
POST /api/ai/openai/image-callbacks/{callbackId}/rotate-secret
A callback can be tested without generating an image:
POST /api/ai/openai/image-callbacks/{callbackId}/dry-run
The dry run uses the same URL checks, signing and delivery format as a real callback and identifies itself with event image_generation.callback_test and dry_run: true.
Delivery status is recorded so a callback can be validated before live image jobs use it.
Callbacks are JSON requests containing:
X-Tools-EventX-Tools-TimestampX-Tools-SignatureX-Tools-DeliveryX-Tools-Signature has the form sha256=<hex digest>.
To verify it, calculate HMAC-SHA256 over:
<TIMESTAMP>.<RAW_JSON_BODY>
Use the callback's signing secret and compare the generated digest with a timing-safe comparison. Receivers should also enforce their own replay-window policy for timestamps.
A callback can subscribe to:
image_generation.completedimage_generation.rejectedimage_generation.failedCompleted payloads can contain the generated image result. Rejected payloads can contain structured moderation details. Retry metadata can include whether retry was attempted, its final state and the adjusted prompt used for the second image attempt.
Provider consumption is attributed to the authenticated user or configured service account.
A reject-retry sequence consumes separate operations:
The existing image usage accounting records each image-provider attempt, and prompt-adjustment usage is also recorded.
Explicit image requests in supported Slack DMs and addressed mentions are routed through the same ToolsAPI image-generation service and access policy as other authenticated image generation. Generated files are uploaded back to the originating Slack conversation or thread.
When recent Slack context is enabled, a short follow-up such as try again, do it now or generate it again can reuse the most recent explicit image request instead of falling through to normal text generation. A retry is only treated as an image request when a previous image request can actually be resolved from the supplied Slack context.
A user can select another OpenAI image model by naming either its canonical ID or a natural GPT Image family name. For example, Generate an image of a lighthouse with gpt-image-1.5, Generate an image with image 1.5, Try again with GPT Image 1.5 and Use image 2 instead are normalized to the corresponding provider model IDs. Canonical IDs such as gpt-image-1-mini continue to work unchanged. The requested model still passes through the normal Tools/OpenAI image policy and provider validation; Slack does not bypass model or account authorization.
The ordinary default remains gpt-image-1 when no image model is requested.
Slack follows its external file-upload flow and sends the generated bytes through the temporary raw upload step. If image generation succeeds but Slack cannot complete delivery, and Tools has already stored the image for the workspace owner, the bot includes an authenticated Tools link to that saved image so the result is not lost. A private saved-image link remains subject to the normal Tools sign-in and owner/admin authorization checks.
X-bot uses the same image job, policy and reject-handling core:
POST /api/x-bot/images
Status:
GET /api/x-bot/images/{sessionId}
X-bot keeps its additional Social Media Tools authorization checks.
When enabled, a restricted public generator is available at /image-generator.
Guest generation is disabled by default and has its own limits for request frequency, prompt length, reference images, models, sizes, quality and reject retry. Guest status URLs include a separate unguessable status token so knowing a job UUID alone is insufficient to read another guest job.
The guest interface intentionally exposes a smaller feature set than authenticated image generation.
Operators can enable image-generation lifecycle reporting through the Tools Slack integration. Reports can include retry start, adjusted-prompt acceptance, completion, rejection and failure information.
Prompt text is excluded from Slack reports by default and is only included when explicitly enabled by the operator.
Clients should distinguish between request/authentication errors when starting a job, queued jobs that later fail and safety rejects where failure_type is rejected. Preserve provider request IDs when diagnosing upstream rejections.
Administrators can manage reusable image bindings at /admin/image-generator/targets. A target connects a stable Tools resource identity to a generated cover, header, thumbnail, social preview or another image purpose while reusing the normal asynchronous Image Generator pipeline.
A target is identified by its service, resource type, resource ID and purpose. Regenerating it keeps the same target identity and stable public image URL; the new image replaces the active binding only after generation has completed successfully. If regeneration fails, the previous working image remains available.
Targets can be public or private. Public targets with a completed image are served from /media/platform-images/{uuid}. Private targets are not exposed through that public route. Uploaded reference images may be used during generation but are not retained as long-lived target configuration.
The target administration page shows generation status and progress, supports requested output dimensions, optional reference images and regeneration, and displays the current preview when one exists.
Documentation cards use the same platform capability. To provide a thumbnail for a documentation page, register a target with service docs, resource type page, the canonical documentation slug as resource ID, and purpose thumbnail. Once that public target has an image, /docs displays it on the matching card; pages without a thumbnail keep the normal text-only layout.