Before I Call GPT Image 2, I Validate These 7 Things An engineer at XPLA detailed a seven-check preflight validation workflow for GPT Image 2 API calls, emphasizing contract-based request validation, dimension conflict checks, and idempotency handling to prevent duplicate billable generations. The approach includes rejecting unsupported fields, storing product identity and allowed transformations, and persisting generation state to reconcile uncertain transport outcomes. I used to debug a bad AI product image by rewriting the prompt. Now I check the request contract first. A GPT Image 2 API request can be valid JSON and still be wrong for the selected model. A generic UI can leak a field from another provider. Two dimension controls can conflict. A timeout can turn one intended image into two generations. A technically successful output can still change the product. This is the seven-check preflight I put in front of the generation call. Disclosure: I work on XPLA. The workflow below is an engineering pattern, not a promise about price, access, speed or image quality. I do not let one universal form submit every visible field to every image model. The application selects a model contract first: js const imageContracts = { "gpt-image-2": { endpoint: "/v1/images/generations", allowed: new Set "model", "prompt", "image", "images", "size", "aspectRatio", "quality", "replyType", "n" , forbidden: new Set "imageSize" } }; The UI should be generated from that record. A control the selected model does not support should not appear. Silently removing an unsupported field creates plausible but uncontrolled outputs. The user chooses a setting, the backend drops it, a default is used, and everyone blames the model. js function rejectUnknownFields body, contract { const errors = ; for const key of Object.keys body { if contract.allowed.has key { errors.push Unsupported field for ${body.model}: ${key} ; } } for const key of contract.forbidden { if body key == undefined { errors.push Forbidden field for ${body.model}: ${key} ; } } return errors; } An explicit local error is easier to fix than an attractive image produced from the wrong request. An image form may expose a ratio, a pixel size, a provider-specific size field and an orientation inferred from the prompt. I allow one supported decision: function validateDimensions body { if body.imageSize == undefined { return "imageSize is not valid for this standard contract" ; } const supplied = body.size == undefined, body.aspectRatio == undefined .filter Boolean .length; return supplied 1 ? "Choose size or aspectRatio, not both" : ; } I store the requested orientation beside the output so QA can verify it. A reference is more than a URL. I store the product identity and the allowed transformation: { "source type": "merchant upload", "rights state": "confirmed for internal calibration", "product id": "merchant-sku-104", "variant": "matte-black-500ml", "must preserve": "single bottle", "matte black body", "silver cap", "existing label geometry" , "allowed changes": "background", "surface", "lighting direction" } A marketplace image being public does not automatically grant permission to download, transform or use it in advertising. This is the operational rule I care about most. If a client times out, it may not know whether the server failed before or after generation. Repeating the request can create another billable task. Before submission, I persist: { "generation id": "img-job-20260902-001", "intent": "new calibration", "request hash": "sha256-of-normalized-request", "state": "submitted", "attempt": 1, "result state": "unknown", "next action": "check before-repeating" } My state transition is: php draft - approved - submitted - completed - accepted | repair | rejected submitted - transport unknown - reconcile before another generation A new creative candidate receives a new generation ID. An uncertain transport result enters reconciliation. I do not hide both actions behind one “Try again” button. For the first run I use: The question is narrow: can the workflow preserve the product facts that matter? More outputs do not improve the evidence if no one reviews them. My QA table looks like this: | Check | Expected | Decision | |---|---|---| | Product count | one unit | accept / repair / reject | | Body color | matte black | accept / repair / reject | | Cap | silver | accept / repair / reject | | Label geometry | unchanged | accept / repair / reject | | Invented claims | none | accept / repair / reject | | Orientation | requested ratio | accept / repair / reject | | Crop safety | fully visible | accept / repair / reject | “Looks good” is not a release decision. An attractive output can still invent a bundle, accessory, certification or quantity. js function preflightGPTImage2 body, rightsRecord { const contract = imageContracts body.model ; const errors = ; if contract errors.push Unknown model contract: ${body.model} ; if body.prompt?.trim errors.push "prompt is required" ; if body.n == undefined && body.n == 1 { errors.push "Use n: 1 and create separate intentional requests" ; } if body.replyType == undefined && body.replyType == "json" { errors.push 'replyType must be "json"' ; } if contract { errors.push ...rejectUnknownFields body, contract ; errors.push ...validateDimensions body ; } if body.image || body.images && rightsRecord?.rights state == "confirmed for internal calibration" { errors.push "Reference-image rights are not confirmed" ; } return { ok: errors.length === 0, errors }; } This is only the request boundary. A production implementation still needs media-type, file-size, URL, privacy, account, policy and storage checks. | Failure class | Example | Default action | |---|---|---| | Client | empty prompt | fix locally | | Contract | unsupported field | reject before submission | | Access | unauthorized key | stop and fix access | | Transport | lost response | reconcile before repeating | | Provider | transient failure | bounded retry policy | | Safety | risky request | stop or revise | | Output QA | altered product | repair or reject | I keep the final order simple: php contract - preflight - approval - one calibration - product QA - intentional scale The current XPLA-specific request shape and model-name boundaries are documented in the GPT Image 2 API guide https://xplaai.com/en-us/api/gpt-image-2/ . Recheck the live contract before production integration.