> ## 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.

# Vectorize an image

> Submit a vectorization job — one source image to SVG — and get a job id back.

Vectorize one source `image` into an SVG. The call returns **`202 Accepted`** with a
job `id`; poll [`GET /images/vectorizations/{id}`](/api-reference/image-ops/get-vectorization)
for the result. The `image` takes **exactly one** of `image_id`, `url`, or
`base64` + `mime_type`. There is **no model parameter**. Requires the
`images.transform` scope.

<Warning>
  **SVG is an EU AI Act Art. 50(2) scope-out.** An SVG cannot carry a C2PA manifest
  or an embedded watermark, so vector outputs are delivered **unsigned and
  unwatermarked**. Delivery is gated on `svg_acceptance` — an explicit acknowledgment
  of this. **The acknowledgment is disclosure / audit evidence, not a compliance
  waiver.**
</Warning>

## Example: one source per mode

`svg_acceptance` must be the literal boolean `true` on every request:

<CodeGroup>
  ```bash image_id theme={null}
  curl -X POST https://api.samsa.ai/public/v1/images/vectorizations \
    -H "Authorization: Bearer $SAMSA_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "image": { "image_id": "123e4567-e89b-12d3-a456-426614174000" },
      "svg_acceptance": true
    }'
  ```

  ```bash url theme={null}
  curl -X POST https://api.samsa.ai/public/v1/images/vectorizations \
    -H "Authorization: Bearer $SAMSA_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "image": { "url": "https://cdn.example.com/logo.png" },
      "svg_acceptance": true,
      "webhook_url": "https://example.com/webhooks/samsa"
    }'
  ```

  ```bash base64 theme={null}
  curl -X POST https://api.samsa.ai/public/v1/images/vectorizations \
    -H "Authorization: Bearer $SAMSA_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "image": { "base64": "iVBORw0KGgoAAAANSUhEUg...", "mime_type": "image/png" },
      "svg_acceptance": true
    }'
  ```
</CodeGroup>

The normal (charged) path returns a `pending` job:

```json 202 Accepted theme={null}
{
  "id": "a8b9c0d1-2e3f-4a4b-5c6d-7e8f9a0b1c2d",
  "status": "pending",
  "estimated_credits": 5
}
```

<Note>
  **Cost = 5 credits on a miss; 0 on a cache hit.** When the source is an `image_id`
  you own and a vector result already exists for it, the submit returns `202` with
  `status: "completed"` and `estimated_credits: 0` immediately — no new job is queued
  and your organization's concurrency cap is not consumed.
</Note>

## Acceptance gates

Vectorization has two independent delivery gates, both enforced with **no charge** on
failure:

* `svg_acceptance` must be the literal boolean `true`. A missing, `false`, or any
  other value is rejected `422 svg_acceptance_required`.
* A **current, server-verified ToS/AUP acceptance** is also required — the request
  flag is never trusted as this fact. A missing or stale acceptance is rejected
  `403 svg_phase1_scope_out_required`; accept the current ToS/AUP and retry.

## Errors

| Status | Code                                                                                                                                                                                                                            | When                                                                                                                                                                                                                                                                                                                                         |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `402`  | [`insufficient_credits`](/guides/errors#insufficient_credits) / [`insufficient_team_credits`](/guides/errors#insufficient_team_credits) / [`insufficient_unallocated_credits`](/guides/errors#insufficient_unallocated_credits) | The balance this credential can spend is below the job cost. Organizations with at least one active team get the team-aware codes instead of `insufficient_credits` (budget-exempt system organizations excepted). An operational failure inside the deduction can still surface as the generic `insufficient_credits`, whatever the regime. |
| `402`  | [`subscription_inactive`](/guides/errors#subscription_inactive)                                                                                                                                                                 | The organization has no usable subscription.                                                                                                                                                                                                                                                                                                 |
| `403`  | [`missing_scope`](/guides/errors#missing_scope)                                                                                                                                                                                 | Key lacks the `images.transform` scope.                                                                                                                                                                                                                                                                                                      |
| `403`  | [`svg_phase1_scope_out_required`](/guides/errors#svg_phase1_scope_out_required)                                                                                                                                                 | The server-verified ToS/AUP scope-out acceptance is missing or stale (no charge).                                                                                                                                                                                                                                                            |
| `404`  | [`not_found`](/guides/errors#not_found)                                                                                                                                                                                         | The source `image_id` is unknown, or not owned by the API key's creator — an image another member of your organization created is a `404` too.                                                                                                                                                                                               |
| `422`  | [`validation_error`](/guides/errors#validation_error)                                                                                                                                                                           | Zero or multiple source modes supplied.                                                                                                                                                                                                                                                                                                      |
| `422`  | [`svg_acceptance_required`](/guides/errors#svg_acceptance_required)                                                                                                                                                             | `svg_acceptance` is not the literal boolean `true` (no charge).                                                                                                                                                                                                                                                                              |
| `429`  | [`rate_limited`](/guides/errors#rate_limited) / [`too_many_active_jobs`](/guides/errors#too_many_active_jobs)                                                                                                                   | Per-key rate window or per-org concurrency cap exceeded.                                                                                                                                                                                                                                                                                     |


## OpenAPI

````yaml api-reference/openapi.json POST /images/vectorizations
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/vectorizations:
    post:
      tags:
        - Images
      summary: Vectorize an image to SVG (Art. 50(2) scope-out)
      description: >-
        Submits a vectorization job — one source `image` — and returns `202`
        immediately with the job `id` and a credit estimate; poll `GET
        /images/vectorizations/{id}` for the result (an SVG). The source is
        exactly one of `image_id` (an image in your organization's context), an
        https `url`, or `base64`+`mime_type`. There is NO model parameter. **SVG
        is a documented EU AI Act Art. 50(2) scope-out:** an SVG cannot carry a
        C2PA manifest or an embedded watermark, so vector outputs are delivered
        UNSIGNED. `svg_acceptance` must be the literal boolean `true` to
        acknowledge this — the acknowledgment is disclosure / audit evidence,
        NOT a compliance waiver; a missing / `false` / other value returns `422
        svg_acceptance_required` with no charge. Delivery ALSO requires a
        current, server-verified ToS/AUP acceptance (the request flag is never
        trusted as that fact); a missing / stale acceptance returns `403
        svg_phase1_scope_out_required` with no charge. **Cost = 5 credits on a
        miss; 0 on a cache HIT.** When the source is an `image_id` you own and a
        vector result already exists for it, the submit returns `202` with
        `status: "completed"` and `estimated_credits: 0` immediately — no new
        job is queued and the per-org concurrency cap is not consumed (an at-cap
        org still gets its cached result); if a `webhook_url` was given the
        `completed` event fires right away. Every other case (an https
        `url`/`base64` source, or an owned `image_id` with no ready result) is
        the normal charged path: `202` with `status: "pending"` and
        `estimated_credits: 5`. Common errors: a foreign or unknown `image_id`
        returns `404`; missing credits or no usable org subscription returns
        `402`; the per-key rate limit or per-org concurrency cap returns `429`.
        Requires the `images.transform` scope.
      operationId: create_image_vectorization_images_vectorizations_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PublicVectorizationRequest'
        required: true
      responses:
        '202':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicTransformAccepted'
        '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:
    PublicVectorizationRequest:
      properties:
        image:
          $ref: '#/components/schemas/PublicImageEditSource'
          description: >-
            The source image: exactly one of `image_id`, an https `url`, or
            `base64`+`mime_type`.
        svg_acceptance:
          type: boolean
          const: true
          title: Svg Acceptance
          description: >-
            Must be the literal boolean `true`: an explicit acknowledgment that
            SVG (vector) output is an EU AI Act Art. 50(2) scope-out delivered
            UNSIGNED and UNWATERMARKED. This acknowledgment is disclosure /
            audit evidence, NOT a compliance waiver. Any other value (missing /
            `false`) is rejected `422 svg_acceptance_required` with no charge.
          examples:
            - true
        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). On a cache hit
            the `completed` event fires immediately.
          examples:
            - https://example.com/webhooks/samsa
      type: object
      required:
        - image
        - svg_acceptance
      title: PublicVectorizationRequest
      description: >-
        `POST /images/vectorizations` body (SAM-821 / S8.9 — Art. 50(2)
        scope-out).


        Vectorize ONE source `image` into an SVG (Recraft; 5 credits flat). The
        source

        is exactly one of `image_id` (an image in your organization's context),
        an

        https `url`, or `base64`+`mime_type`. There is NO model parameter.


        **SVG is a documented EU AI Act Art. 50(2) scope-out:** an SVG cannot
        carry a

        C2PA manifest or an embedded watermark, so vector outputs are delivered

        unsigned. Delivery is therefore gated on `svg_acceptance` — an explicit

        acknowledgment that the SVG is an unsigned, unwatermarked scope-out
        output.

        **This acknowledgment is disclosure / audit evidence, NOT a compliance

        waiver.** `svg_acceptance` must be the literal boolean `true`; a
        missing,

        `false`, or any other value is rejected `422 svg_acceptance_required`
        with no

        charge. Delivery ALSO requires a current, server-verified ToS/AUP
        acceptance

        (the request flag is never trusted as that fact); a missing / stale
        acceptance

        is `403 svg_phase1_scope_out_required` with no charge.


        **Cost = 5 credits on a miss; 0 on a cache HIT.** When the source is an

        `image_id` you own and a vector result already exists for it, the submit

        returns `202` with `status: "completed"` and `estimated_credits: 0`
        immediately

        (no new job is queued and the org's concurrency cap is not consumed).
      examples:
        - image:
            image_id: 123e4567-e89b-12d3-a456-426614174000
          svg_acceptance: true
        - image:
            url: https://cdn.example.com/logo.png
          svg_acceptance: true
          webhook_url: https://example.com/webhooks/samsa
        - image:
            base64: iVBORw0KGgoAAAANSUhEUg...
            mime_type: image/png
          svg_acceptance: true
    PublicTransformAccepted:
      properties:
        id:
          type: string
          format: uuid
          title: Id
          description: The job id — poll the op's `GET .../{id}` endpoint.
        status:
          $ref: '#/components/schemas/PublicImageStatus'
          description: >-
            Initial status: `pending` (job queued — enter the polling flow), or
            `completed` with `estimated_credits: 0` when `background-removals` /
            `vectorizations` serve an owned-image cache hit (the result is
            immediately available).
          examples:
            - pending
        estimated_credits:
          type: integer
          title: Estimated Credits
          description: >-
            Credits this job is expected to cost — `0` on a cache-hit
            `completed` response.
          examples:
            - 5
      type: object
      required:
        - id
        - status
        - estimated_credits
      title: PublicTransformAccepted
      description: >-
        Shared `202` body for the transform-op submits (SAM-813 / S8 wave).


        Every `POST /images/<op>` returns the async job handle

        `{id, status, estimated_credits}`. The initial `status` is `pending`
        (the

        job is queued), with ONE exception: `background-removals` and

        `vectorizations` answer an owned-`image_id` cache hit (a ready result

        already exists for that image) with `status: "completed"` and

        `estimated_credits: 0` — no new job is queued, the `completed` webhook

        event is emitted immediately for a supplied `webhook_url`, and the
        result

        is already available from the op's `GET .../{id}` endpoint. The other

        transform ops (`img2img`, `variations`, `resizes`, `upscales`) always

        start `pending`.
    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`.


        `url` / `base64` rasters must decode to at most **33,554,432 pixels**

        (32 MP, width x height) — a larger source returns `422` naming the
        source

        param, before any charge (same ceiling the resize op documents).
    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_...`.

````