> ## Documentation Index
> Fetch the complete documentation index at: https://docs.samsa.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Edit an image

> Submit a Magic Edit job — a source image plus a prompt, optionally masked and styled.

Submit a source image and a prompt describing the edit. The call returns
**`202 Accepted`** with a job `id`; poll
[`GET /images/edits/{id}`](/api-reference/edits/get-edit) for the result. The
`image` object takes **exactly one** of `image_id`, `url`, or `base64` + `mime_type`.

## Example: masked edit from a URL

Provide the source by `url`, add an inpaint `mask` (its presence selects PRO mode),
and reuse a `style` model. The `mask` is a base64-encoded image marking the region
to edit.

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.samsa.ai/public/v1/images/edits \
    -H "Authorization: Bearer $SAMSA_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "image": { "url": "https://cdn.example.com/product-photo.png" },
      "prompt": "Replace the plain background with our branded gradient",
      "mask": { "base64": "iVBORw0KGgoAAAANSUhEUgAA...." },
      "style_id": "2b9d1f7a-3c4e-4a5b-9c8d-0e1f2a3b4c5d",
      "engine": "nano_banana_pro",
      "resolution": "1K",
      "num_images": 1
    }'
  ```

  ```json Body theme={null}
  {
    "image": { "url": "https://cdn.example.com/product-photo.png" },
    "prompt": "Replace the plain background with our branded gradient",
    "mask": { "base64": "iVBORw0KGgoAAAANSUhEUgAA...." },
    "style_id": "2b9d1f7a-3c4e-4a5b-9c8d-0e1f2a3b4c5d",
    "engine": "nano_banana_pro",
    "resolution": "1K",
    "num_images": 1
  }
  ```
</CodeGroup>

<Note>
  Send **exactly one** source mode in `image`. Omit `mask` for a text-only (SIMPLE)
  edit. `resolution` applies only to `nano_banana_pro`; omit it for the other
  engines. `num_images` (1–4) defaults to **1**.
</Note>


## OpenAPI

````yaml api-reference/openapi.json POST /images/edits
openapi: 3.1.0
info:
  title: Samsa API
  description: >-
    The Samsa public REST API. Authenticate with an organization API key as a
    bearer token (`Authorization: Bearer samsa_sk_...`). Errors follow a single
    envelope shape; every response carries an `X-Request-ID`.
  version: 1.0.0
servers:
  - url: https://api.samsa.ai/public/v1
security:
  - BearerAuth: []
paths:
  /images/edits:
    post:
      tags:
        - Images
      summary: Edit an image with a prompt
      description: >-
        Submits an image-edit job and returns `202` immediately with the job
        `id` and a credit estimate; poll `GET /images/edits/{id}` for the
        result. Provide a `prompt` and a source `image` (exactly one of
        `image_id`, an https `url`, or `base64`+`mime_type`). Add an optional
        `mask` (auto-selects PRO / mask-based mode — `nano_banana_pro`/`gemini`
        only), your organization's trained models (`style_id`, `object_ids`,
        `person_ids`, `setting_ids`, `color_palette_id` — any of these forces
        the `nano_banana_pro` engine), and an `engine` (`nano_banana_pro`
        default, `gemini`, `kontext`). `num_images` defaults to **1**; each
        output is billed at `5 x resolution_multiplier` credits for
        `nano_banana_pro` (1K:1x, 2K:2x, 4K:4x), else `5`. Requires the
        `images.edit` scope.
      operationId: create_image_edit_images_edits_post
      parameters:
        - name: authorization
          in: header
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            title: Authorization
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PublicImageEditRequest'
      responses:
        '202':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicImageEditAccepted'
        '401':
          description: Missing, invalid, expired, or revoked API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '402':
          description: Insufficient credits, or no usable org subscription.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '403':
          description: The API key lacks the required scope for this operation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '404':
          description: Generation, or a referenced model/palette, not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '409':
          description: A referenced model is not ready for generation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '422':
          description: Request validation failed (prompt, engine, resolution, ...).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '429':
          description: Per-key rate limit or per-org concurrency cap exceeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '500':
          description: Internal server error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
components:
  schemas:
    PublicImageEditRequest:
      properties:
        image:
          $ref: '#/components/schemas/PublicImageEditSource'
          description: >-
            The source image: exactly one of `image_id`, `url`, or
            `base64`+`mime_type`.
        prompt:
          type: string
          minLength: 1
          title: Prompt
          description: >-
            Text prompt describing the edit. Runs the same validation as the app
            (rejects empty / malformed / policy-violating prompts with a `422`).
          examples:
            - Replace the sky with a dramatic sunset
        mask:
          anyOf:
            - $ref: '#/components/schemas/PublicImageEditMask'
            - type: 'null'
          description: >-
            Optional inpaint mask. When present, the edit runs in PRO
            (mask-based) mode — supported only by the `nano_banana_pro` and
            `gemini` engines (or when trained models force `nano_banana_pro`).
        engine:
          anyOf:
            - type: string
            - type: 'null'
          title: Engine
          description: >-
            Edit engine — one of `nano_banana_pro` (default), `gemini`, or
            `kontext`. Omit to use the default. Unknown engines return `422`.
          examples:
            - nano_banana_pro
        style_id:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
          title: Style Id
          description: A `style` model in your organization (forces `nano_banana_pro`).
        object_ids:
          items:
            type: string
            format: uuid
          type: array
          title: Object Ids
          description: '`object` models in your organization to compose in.'
        person_ids:
          items:
            type: string
            format: uuid
          type: array
          title: Person Ids
          description: '`person` models in your organization to compose in.'
        setting_ids:
          items:
            type: string
            format: uuid
          type: array
          title: Setting Ids
          description: '`setting` models in your organization (maps to internal scenes).'
        color_palette_id:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
          title: Color Palette Id
          description: A color palette in your organization (forces `nano_banana_pro`).
        resolution:
          anyOf:
            - type: string
            - type: 'null'
          title: Resolution
          description: >-
            Output resolution — `1K`, `2K`, or `4K`. Only the `nano_banana_pro`
            engine supports it (credits scale 1K:1x, 2K:2x, 4K:4x; omitted =
            `1K`); omit for the other engines.
          examples:
            - 1K
        num_images:
          type: integer
          maximum: 4
          minimum: 1
          title: Num Images
          description: >-
            Number of edited images to generate (1-4). Defaults to **1**; each
            output is billed.
          default: 1
          examples:
            - 1
        output_format:
          $ref: '#/components/schemas/PublicImageOutputFormat'
          description: Encoding of the returned images. v1 supports `png` only.
          default: png
          examples:
            - png
        webhook_url:
          anyOf:
            - type: string
            - type: 'null'
          title: Webhook Url
          description: >-
            Optional https webhook notified once on terminal status (signed per
            the webhook signature scheme; see the webhooks docs).
          examples:
            - https://example.com/webhooks/samsa
      type: object
      required:
        - image
        - prompt
      title: PublicImageEditRequest
      description: >-
        `POST /images/edits` body (ADR §8, §10) — Magic Edit.


        Supply a `prompt` and a source `image`; optionally a `mask`
        (auto-selects PRO

        mode), your organization's trained models
        (`style_id`/`object_ids`/`person_ids`/

        `setting_ids`, `color_palette_id` — any of these forces the
        `nano_banana_pro`

        engine, mirroring the app), and an `engine` (a public-safe alias of the
        internal

        edit model). `num_images` defaults to **1**.
    PublicImageEditAccepted:
      properties:
        id:
          type: string
          format: uuid
          title: Id
          description: The image-edit job id — poll `GET /images/edits/{id}`.
        status:
          $ref: '#/components/schemas/PublicImageStatus'
          description: 'Initial status: always `pending` at submit.'
          examples:
            - pending
        estimated_credits:
          type: integer
          title: Estimated Credits
          description: >-
            Credits this job is expected to cost (base 5 x num_images x
            resolution multiplier for `nano_banana_pro`).
          examples:
            - 5
      type: object
      required:
        - id
        - status
        - estimated_credits
      title: PublicImageEditAccepted
      description: '`202` body for `POST /images/edits` (ADR §7.1).'
    ErrorEnvelope:
      properties:
        error:
          $ref: '#/components/schemas/ErrorDetail'
      type: object
      required:
        - error
      title: ErrorEnvelope
      description: The complete public error body — an ``error`` object wrapper (ADR §5).
    PublicImageEditSource:
      properties:
        image_id:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
          title: Image Id
          description: Id of an image in your organization's context to edit.
        url:
          anyOf:
            - type: string
            - type: 'null'
          title: Url
          description: https URL of the source image (downloaded under SSRF guards).
          examples:
            - https://cdn.example.com/photo.png
        base64:
          anyOf:
            - type: string
            - type: 'null'
          title: Base64
          description: Base64-encoded source image bytes (send with `mime_type`).
        mime_type:
          anyOf:
            - type: string
            - type: 'null'
          title: Mime Type
          description: >-
            MIME type for a base64 source — one of: image/jpeg, image/png,
            image/webp.
          examples:
            - image/png
      type: object
      title: PublicImageEditSource
      description: >-
        The source image for an edit — exactly one of three modes (ticket §1).


        * `image_id` — an image already in the key creator's context (owned by
        the key
          creator; ownership is enforced in the route -> `404` on a miss).
        * `url` — an `https` URL the server downloads under the SSRF guard
        (§7.4).

        * `base64` + `mime_type` — inline bytes (`mime_type` in the allow-list).


        Exactly one mode must be supplied; zero or more than one is a `422`.
    PublicImageEditMask:
      properties:
        base64:
          type: string
          minLength: 1
          title: Base64
          description: Base64-encoded mask image (the region to edit).
      type: object
      required:
        - base64
      title: PublicImageEditMask
      description: >-
        An inpaint mask whose PRESENCE selects PRO (mask-based) mode.


        Mirrors the internal flow (`InpaintRequest` auto-selects PRO when a mask
        is

        supplied); its absence is SIMPLE (text-only) mode.
    PublicImageOutputFormat:
      type: string
      enum:
        - png
      title: PublicImageOutputFormat
      description: >-
        Public output format for generated images.


        v1 exposes ``png`` only: both public engines route through the Gemini
        path,

        which reliably returns PNG and does NOT convert to ``jpeg``/``webp`` (it
        would

        accept the request, charge, and still return PNG — a misleading
        contract). The

        other formats are deferred until the generation path converts them
        (SAM-623).
    PublicImageStatus:
      type: string
      enum:
        - pending
        - processing
        - completed
        - failed
        - cancelled
      title: PublicImageStatus
      description: >-
        Public image-job status — the lower-cased internal ``TaskStatus``.


        Deliberately the plain lower-cased internal value (NOT the ADR §7.2

        ``PENDING -> queued`` remap): the ticket's 202 uses ``status:
        "pending"`` and

        its fixtures say ``pending/processing/completed/failed``, and this keeps
        the

        public surface consistent with the already-shipped models API

        (``PublicModelStatus``).
    ErrorDetail:
      properties:
        type:
          type: string
          title: Type
          examples:
            - authentication_error
        code:
          type: string
          title: Code
          examples:
            - invalid_api_key
        message:
          type: string
          title: Message
          examples:
            - The provided API key is invalid, expired, or revoked.
        request_id:
          type: string
          title: Request Id
          examples:
            - 8f14e45fceea167a5a36dedd4bea2543
        param:
          anyOf:
            - type: string
            - type: 'null'
          title: Param
          description: Present on validation errors — names the offending field.
          examples:
            - aspect_ratio
      type: object
      required:
        - type
        - code
        - message
        - request_id
      title: ErrorDetail
      description: The ``error`` object of the public envelope (ADR §5).
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: >-
        Organization API key as a bearer token: `Authorization: Bearer
        samsa_sk_...`.

````