Sign Customiser

Navigation

Dark mode

AI sign designs

create_ai_sign_design_job

destructive write

Create AI sign design job

Copy page

Turn an uploaded logo or artwork image into a sign design with SVG and optional EPS and Illustrator-compatible PDF files.

Overview

Start one AI sign design from an uploaded source and a product family, or from a customiser of this store. The source image is sent to the external AI image providers that the AI sign designer uses. One credit is held now, charged when the design is delivered, and released if the design fails. The source can start one design only. The job runs in the background: read it with get_ai_sign_design_job. Requires ai_sign_designs:write, and customisers:read for a customiser. An actual job needs confirm: true, max_credits: 1 and an idempotency_key that is bound to the exact source, context and output formats. Supports dry_run, which holds no credit and starts nothing.

Permission

Requires theai_sign_designs:writepermission. A connection without it answersinsufficient_scopenaming the permission to approve.

Annotations

readOnlyHintfalse
destructiveHinttrue
idempotentHinttrue
openWorldHinttrue

Prerequisites

  • A source whose status is uploaded, from create_ai_sign_design_source and a PUT of the image bytes.
  • A merchant has connected this store and approved the ai_sign_designs:write scope. A customiser_id also needs customisers:read.
  • The merchant agrees to spend one credit. Call get_ai_sign_design_capabilities to see the available credits.

Side effects

  • Uses the source. It cannot start another design.
  • Holds one credit of the store. Delivery charges it; a failed design releases it.
  • Sends the source image to the external AI image providers that the AI sign designer uses.
  • Claims the idempotency_key for at least 24 hours.

Arguments

source_idstringrequired

The id of an uploaded source from create_ai_sign_design_source.

product_familystring

The kind of sign for a standalone design. Required unless customiser_id is sent; with a customiser it must be the customiser family or omitted. Expected to grow.

One of: neon, channel_letter, metal_cut_out

customiser_idinteger

A customiser of this store, from list_customisers, to design in its context. Needs customisers:read.

letter_type_idinteger

A letter type of the customiser, from list_customiser_options. Only with customiser_id.

output_formatsarray of string

The files to make. SVG is always made. Omit for every format, or send ["svg"] for SVG only.

max_creditsintegerrequired unless dry_run is true

The most credits this job can spend, which must be 1: a delivered design uses one credit and a failed design uses none.

confirmbooleanrequired unless dry_run is true

Must be true to apply the change, because the job holds one credit of the store, uses the source, and sends the image to external AI image providers. Without it the call returns a confirmation_required error and changes nothing.

idempotency_keystringrequired unless dry_run is true

A client-generated key unique to this logical write, such as a UUID. Required: repeating the call with the same key and the same arguments replays the original result instead of writing twice, and the same key with different arguments is an idempotency_key_conflict.

dry_runboolean

When true, the job is checked against the source, the context, the capacity and the available credits is checked and nothing is written: the result is the same verdict the apply would have reached, and a problem the apply would have raised comes back as the same tool error. Defaults to false. A dry run claims no key. A dry run does not require the confirm argument.

Result

The job in queued state, with its charge and poll_after_seconds. Read it again with get_ai_sign_design_job until status is delivered or failed. A dry run returns the resolved product family, the credits a job needs and the credits available, and holds nothing.

request_idstringalways present
storeobjectalways present
store.idintegeralways present
store.namestringalways present
jobobject

The admitted job. Absent on a dry run.

job.idstringalways present
job.statusstringalways present

queued, processing, delivered (one credit charged) or failed (no credit charged). Expected to grow: tolerate unknown values.

One of: queued, processing, delivered, failed

job.product_familystringalways present

One of: neon, channel_letter, metal_cut_out

job.customiser_idinteger or null
job.letter_type_idinteger or null
job.source_fileobjectalways present
job.source_file.idstringalways present
job.source_file.media_typestring or null
job.source_file.byte_sizeinteger or null
job.source_file.width_pxinteger or null
job.source_file.height_pxinteger or null
job.source_file.download_urlstring or null
job.output_formatsarray of stringalways present
job.poll_after_secondsinteger or null

While the job runs, how long to wait before reading it again. Null once it is delivered or failed.

job.resultobject or null

The delivered design, or null until delivery and for an erased design. Each ready file has a download_url that needs no login and can be given to a manufacturer.

job.result.display_treatmentstring or null
job.result.filesobject
job.result.assessed_dimensionsobject or null
job.result.advisoriesarray of object
job.result.export_retries_remaininginteger
job.chargeobjectalways present

reserved while the credit is held, charged once the design is delivered, released when the design failed.

job.charge.statestringalways present

One of: reserved, charged, released

job.charge.unitsintegeralways present
job.errorobject or null
job.error.codestringalways present
job.error.detailstringalways present
job.created_atstringalways present
job.completed_atstring or null
idempotent_replayboolean

True when this call replayed a previously recorded response for the same idempotency_key instead of applying the write again.

dry_runboolean

Present and true only when dry_run was requested.

validboolean

Present only on a dry run, and always true: a failing dry run returns a tool error instead.

verdictobject

Present only on a dry run: the resolved product family, the credits a job needs and the credits available now.

verdict.operationstring
verdict.product_familystring
verdict.required_unitsinteger
verdict.available_unitsinteger

Error cases

ai_sign_design_capacity_reached

The most jobs that can run at the same time are running. Wait retry_after seconds and send the identical call again.

ai_sign_design_context_required

Send product_family for a standalone design, or customiser_id.

ai_sign_designer_unavailable

The AI sign designer cannot start jobs for this store now. Nothing was held.

confirmation_required

Send confirm: true after the merchant agrees to spend one credit.

idempotency_key_conflict

The key was used for a different source, context or output formats. Confirm the new job again with a new key.

insufficient_credits

The store has no available credit. Nothing was held and the source is still usable.

insufficient_scope

The connection was approved without ai_sign_designs:write, or without customisers:read for a customiser.

product_family_conflict

product_family differs from the family of the customiser. Omit it or use the value in allowed_values.

rate_limited

This connection started too many jobs in the last minute. Wait retry_after seconds.

resource_not_found

The source, customiser or letter type does not exist for this connection and store.

source_already_consumed

Another job used the source. Declare a new source for another design.

source_expired

The source expired. Declare a new source and upload the image again.

source_not_uploaded

No bytes arrived for the source. PUT the image to its target first.

source_rejected

The image failed verification. Correct it and declare a new source.

validation_failed

A field has a value the job does not accept. allowed_values lists the accepted values.

Start a neon design that makes every file

tools/call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_ai_sign_design_job",
    "arguments": {
      "source_id": "aisrc_9f2c4b7ad13e6058ba41cd4201",
      "product_family": "neon",
      "confirm": true,
      "max_credits": 1,
      "idempotency_key": "3c1e5a7b-9d2f-4b6a-8c0e-1f3a5b7c9d2e"
    }
  }
}
result
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "structuredContent": {
      "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t",
      "store": {
        "id": 12,
        "name": "Demo Signs"
      },
      "job": {
        "id": "aijob_4k8m2p6r0t3v7x1z5b9d3f7h2j",
        "status": "queued",
        "product_family": "neon",
        "customiser_id": null,
        "letter_type_id": null,
        "source_file": {
          "id": "aisrc_9f2c4b7ad13e6058ba41cd4201",
          "media_type": "image/png",
          "byte_size": 482133,
          "width_px": 1600,
          "height_px": 900,
          "download_url": null
        },
        "output_formats": [
          "svg",
          "eps",
          "illustrator_pdf"
        ],
        "poll_after_seconds": 5,
        "result": null,
        "charge": {
          "state": "reserved",
          "units": 1
        },
        "error": null,
        "created_at": "2026-10-20T09:31:00Z",
        "completed_at": null
      },
      "idempotent_replay": false
    }
  }
}

Check a job as a dry run

tools/call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_ai_sign_design_job",
    "arguments": {
      "source_id": "aisrc_9f2c4b7ad13e6058ba41cd4201",
      "product_family": "neon",
      "dry_run": true
    }
  }
}
result
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "structuredContent": {
      "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t",
      "store": {
        "id": 12,
        "name": "Demo Signs"
      },
      "dry_run": true,
      "valid": true,
      "verdict": {
        "operation": "create",
        "product_family": "neon",
        "required_units": 1,
        "available_units": 42
      }
    }
  }
}

Without confirmation no credit is held (error)

tools/call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_ai_sign_design_job",
    "arguments": {
      "source_id": "aisrc_9f2c4b7ad13e6058ba41cd4201",
      "product_family": "neon",
      "confirm": false,
      "max_credits": 1,
      "idempotency_key": "3c1e5a7b-9d2f-4b6a-8c0e-1f3a5b7c9d2e"
    }
  }
}
result
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "isError": true,
    "structuredContent": {
      "error": {
        "code": "confirmation_required",
        "title": "Confirmation required",
        "detail": "This AI sign design job holds one credit of the store and sends the source image to external AI image providers.",
        "recovery": "This operation changes something consequential. Send confirm: true once the merchant has agreed to it.",
        "parameter": "confirm",
        "allowed_values": [
          "true"
        ]
      }
    }
  }
}

A store with no available credit (error)

tools/call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "create_ai_sign_design_job",
    "arguments": {
      "source_id": "aisrc_9f2c4b7ad13e6058ba41cd4201",
      "product_family": "neon",
      "confirm": true,
      "max_credits": 1,
      "idempotency_key": "3c1e5a7b-9d2f-4b6a-8c0e-1f3a5b7c9d2e"
    }
  }
}
result
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "isError": true,
    "structuredContent": {
      "error": {
        "code": "insufficient_credits",
        "title": "Insufficient credits",
        "detail": "A design job reserves 1 credit before it starts, and this store has 0 available. Nothing was reserved, and the source was not used. Add credits in the merchant admin, then retry with the same source.",
        "recovery": "The store has fewer available credits than required_units. Nothing was held and the source was not used. Ask the merchant to add credits in the merchant admin, then send the identical call again.",
        "required_units": 1,
        "available_units": 0
      }
    }
  }
}

Type a question and press Enter. Use the arrow keys to move between the results.