# info.description
Provider-neutral print catalog and prepared-media validation. This document covers only routes owned by the Go service; it deliberately excludes migration-proxied order lifecycle routes and all provider payloads.

# paths./v1/catalog/products/{product_id}.get.summary
Get the latest revision of one canonical product

# paths./v1/catalog/shipping-services.get.description
Zapier-safe public discovery metadata for currently supported automation choices. Base amounts and eligibility are schedule guidance only: the exact quote may be higher or the service may be unavailable. Quote the complete order to determine its final available service and charge. One-day service values remain accepted by order endpoints but are intentionally not published until generally supported.

# paths./v1/print-orders/validate.post.summary
Validate a provider-neutral prepared-media print order

# paths./v1/print-orders/validate.post.description
Accepts exactly one JSON object up to 2 MiB and rejects unknown fields. This endpoint does not quote, create, pay for, upload media for, or submit an order. Clients must fetch the catalog and use the selected product revision's asset requirements, text requirements, and options. A prepared background is supplied as an HTTPS asset URL; this API version does not publish hosted theme or design catalogs.

# paths./v1/assets/ingest.post.summary
Copy one external image into Batch Relay-managed fulfillment storage

# paths./v1/assets/ingest.post.description
Requires print_orders:write and an Idempotency-Key up to 200 characters. Supply exactly one source: an externally routable HTTPS url is downloaded with SSRF protections, content-validated, SHA-256-addressed, and written immutably to the fulfillment R2 scope; an asset_id is resolved as a ready unexpired same-account external asset or a finalized same-studio platform image and is never copied. Source URLs are not fulfillment URLs and are not retained in the managed asset record.

# paths./v1/assets/ingest.post.parameters[].description
Required stable key for the managed ingestion request; reuse with a different URL/source is rejected.

# paths./v1/templates/{template_id}/renders.post.summary
Create a render from a published template

# paths./v1/templates/{template_id}/renders.post.description
Requires a studio-owned API account with the print_orders:write key scope. Accepts explicit stable slot IDs only. Omit revision_id to resolve the latest published revision; the response snapshots the resolved immutable revision. The service does not infer input order or fetch arbitrary caller URLs. Convex durably queues this job; the local API does not embed or dispatch the private renderer.

# paths./v1/templates/{template_id}/renders.post.parameters[].description
Retries with the same key return the durable render job; reuse with a different request returns idempotency_conflict.

# paths./v1/templates/{template_id}/renders.post.responses.202.description
Render queued, running, succeeded, or failed. Artifacts are always an array so multi-surface output is representable.

# paths./v1/templates/{template_id}/outputs/{output_id}/contract.get.summary
Get one published output's render contract

# paths./v1/templates/{template_id}/outputs/{output_id}/contract.get.description
Requires a studio-owned API account with the print_orders:read key scope. Omit revision_id to resolve the latest published revision. Returned slot key is the only runtime identity; ordinal, label, and semantic suggestion are revision-local discovery metadata.

# paths./v1/templates/{template_id}/outputs/{output_id}/contract.get.parameters[].description
Optional immutable published or superseded revision ID.

# paths./v1/renders/{render_id}.get.summary
Get a template render and its output artifacts

# paths./v1/renders/{render_id}.get.description
Requires the studio-owned API account that owns the render and the print_orders:read key scope.

# paths./v1/print-orders/quote.post.summary
Create a server-calculated API order quote

# paths./v1/print-orders/quote.post.description
Requires a scoped API key. Price, tax, shipping, and platform fee are server-calculated. Each asset supplies exactly one source: asset_id reuses an owned immutable Batch Relay asset, while url is copied into managed fulfillment storage during quote creation. URL quotes require Idempotency-Key; the submitted order is fulfilled from the quote-owned frozen snapshot and never re-fetches the source URL. Use the wrapper to select a provider explicitly or bind the quote to an event; a legacy bare OrderRequest continues to resolve through the account/event/default routing policy.

# paths./v1/providers/compatibility.post.summary
Preview one provider's compatibility for a canonical order

# paths./v1/providers/compatibility.post.description
Resolves exactly one provider using the same explicit/event/default precedence as quoting. It never splits lines, substitutes products, creates a quote, payment, or provider order.

# paths./v1/print-orders.post.description
Requires a scoped API key and Idempotency-Key. The quote is account/environment scoped and freezes exactly one resolved provider; submission cannot alter it or split a mixed-provider order.

# paths./v1/api-account.get.description
Requires a verified Batch Relay dashboard session. The requested account is authorized server-side; this route fails closed until the host configures the Clerk and Convex adapters.

# paths./v1/api-account.post.summary
Create an individual or studio-owned API account

# paths./v1/api-account.post.description
A verified individual may create their own individual account. A studio account is created only after server-side studio owner/admin authorization.

# paths./v1/api-account/billing/setup-sessions.post.description
Creates a server-side Stripe-hosted setup session for an authorized account. No card data is accepted by Batch Relay. A completed browser redirect does not activate billing; the verified Stripe webhook does.

# components.securitySchemes.bearerAuth.description
Batch Relay scoped API key, not OAuth. Scope names document required key capabilities.

# components.responses.InvalidRequestJSON.description
The body was malformed, contained unknown fields, or was not exactly one JSON object.

# components.responses.OrderValidationFailed.description
The order did not satisfy the catalog, option, quantity, address, or prepared-media requirements.

# components.responses.InvalidAssetSource.description
The source was missing, ambiguous, unsafe, unsupported, or could not be decoded as an allowed image.

# components.responses.AssetTooLarge.description
The source image exceeded the managed-ingestion size limit.

# components.responses.AssetSourceFetchFailed.description
The source image could not be fetched over HTTPS. The response distinguishes an upstream HTTP error, timeout, or unreachable host without exposing upstream response content.

# components.responses.ManagedAssetUnavailable.description
Private R2 storage or managed asset resolution is not configured.

# components.responses.InvalidRenderRequest.description
The render body was malformed or contained unknown fields.

# components.responses.TemplateRenderValidationFailed.description
The render request did not provide explicit valid input slots.

# components.responses.TemplateRenderUnavailable.description
The stateful template store or private renderer bridge is not configured.

# components.responses.TemplateRenderNotFound.description
The requested render does not exist or is not visible to the caller.

# components.responses.InvalidTemplateContractRequest.description
The template, output, or revision identifier was invalid.

# components.responses.TemplateContractUnavailable.description
The authoritative template-contract bridge is not configured.

# components.responses.TemplateContractNotFound.description
The published output contract does not exist or is not visible to the caller.

# components.responses.APIKeyAuthenticationRequired.description
A valid Batch Relay API key is required.

# components.responses.APIKeyForbidden.description
The API key cannot perform this operation.

# components.responses.StatefulAPIUnavailable.description
The stateful order service is not configured or is temporarily unavailable.

# components.responses.PaymentRequired.description
Payment method setup or customer action is required before fulfillment.

# components.responses.IdempotencyConflict.description
The idempotency key has already been used with a different request.

# components.responses.APIOrderNotFound.description
The order does not exist for this API account.

# components.responses.ManagementAuthenticationRequired.description
A verified Batch Relay dashboard session is required.

# components.responses.APIAccountForbidden.description
The authenticated user cannot operate this API account.

# components.responses.ManagementUnavailable.description
The management auth, account, or billing command bridge is not configured or temporarily unavailable.

# components.schemas.ShippingServiceCatalog.description
Versioned V1 automation discovery metadata. The exact quote may be higher or the service may be unavailable.

# components.schemas.ShippingServiceCatalog.properties.shipping_catalog_revision.description
Stable Batch Relay revision of the published service labels, base amounts, and constraints.

# components.schemas.ShippingServiceCatalogEntry.properties.base_amount_cents.description
Reviewed schedule base in minor currency units, not a final shipping quote.

# components.schemas.ShippingServiceCatalogEntry.properties.base_amount_label.description
Ready-to-display schedule-base copy for an automation form. It is not a final shipping quote.

# components.schemas.ShippingServiceCatalogEntry.properties.eligibility.description
Concise schedule constraints. The exact quote may be higher or the service may be unavailable.

# components.schemas.Product.properties.units_per_quantity.description
Physical units produced by one line quantity.

# components.schemas.Product.properties.text_requirements.description
Provider-neutral ordered text slots supported by this product. The current catalog publishes six generic Memory Mate slots while final visual/provider field labels are under verification; clients must use the returned slot IDs rather than infer provider node IDs.

# components.schemas.Product.properties.template_requirement.description
When present, quote and order require a succeeded Batch Relay template render; raw uploads and caller-declared provenance do not satisfy this requirement.

# components.schemas.Product.properties.fulfillment_target.description
The standard physical product used for provider-neutral routing after a composed product has flattened to finished artwork.

# components.schemas.ProductOption.properties.affects_price.description
Whether a selected value can change the provider unit cost.

# components.schemas.ProductLifecycle.properties.replacement_product_id.description
A recommended canonical replacement. Deprecated products remain decodable for historical records but cannot be planned for new fulfillment.

# components.schemas.UnitCost.properties.unit_cost_cents.description
Provider PPU in cents. Null means the price is not yet established; zero is a real zero price.

# components.schemas.UnitCost.properties.pricing_status.description
Confidence state for this exact option combination.

# components.schemas.AssetRequirement.properties.rotation_policy.description
Whether the prepared asset may use the transposed aspect orientation. Fixed is the default for templates and multi-asset layouts.

# components.schemas.AssetIngestionRequest.properties.url.description
One external source. It is downloaded and never retained as the fulfillment URL.

# components.schemas.AssetIngestionRequest.properties.asset_id.description
One already-finalized Batch Relay or platform image asset. It is resolved and reused without a byte copy.

# components.schemas.IngestedAsset.properties.asset_id.description
Opaque identifier for later managed-asset attachment.

# components.schemas.IngestedAsset.properties.storage_scope.description
External URL ingress always returns fulfillment; private delivery uses this scope plus object-key lookup.

# components.schemas.IngestedAsset.properties.reused.description
True when the same immutable object already existed or a finalized asset_id was reused.

# components.schemas.PreparedAsset.description
Internal provider-ready asset snapshot. Public print-order endpoints use OrderAssetSource instead.

# components.schemas.PreparedAsset.properties.file_size_bytes.description
Required by quote and submit API routes.

# components.schemas.PreparedAsset.properties.format.description
Required by quote and submit API routes.

# components.schemas.OrderAssetSource.description
Public asset source. Supply role plus exactly one of url or asset_id. Batch Relay resolves and freezes immutable metadata during quote; optional metadata is a non-authoritative preflight hint. Products with template_requirement=required accept only the asset_id from a succeeded Batch Relay template render plus template_render_id. Public submission never passes a source URL to a provider.

# components.schemas.OrderAssetSource.properties.url.description
HTTPS source copied into managed fulfillment storage during quote.

# components.schemas.OrderAssetSource.properties.asset_id.description
Existing authorized bra_ managed asset or same-studio image asset; reused in place.

# components.schemas.OrderAssetSource.properties.template_render_id.description
Required with asset_id for a template-required product. Batch Relay verifies the succeeded render owns the selected artifact.

# components.schemas.OrderAssetSource.properties.origin.description
Ignored for template provenance; the server derives it from template_render_id.

# components.schemas.TextRequirement.properties.name.description
Current public label. Memory Mate labels are intentionally generic while final visual/provider-field mapping is under verification.

# components.schemas.TemplateRenderInput.properties.asset_id.description
An authorized opaque prepared/source asset identifier. The render service resolves it; callers cannot provide arbitrary URLs.

# components.schemas.TemplateRenderCreateRequest.properties.revision_id.description
Optional immutable template revision. When omitted, Batch Relay resolves the latest published revision and returns it in template.revision_id.

# components.schemas.TemplateRenderCreateRequest.properties.output_id.description
A published one- or multi-surface output selector, such as print-8x10-portrait or trader-card-double-sided. It owns the selected surface variants.

# components.schemas.TemplateRenderCreateRequest.properties.inputs.description
Explicit stable slot ID to value mapping. Labels and positional order are never interpreted by the API.

# components.schemas.TemplateRenderArtifact.properties.surface_id.description
The rendered surface, such as front, back, or print.

# components.schemas.TemplateRenderArtifact.properties.fulfillment_role.description
Only final fulfillment-ready artwork surfaces are exposed.

# components.schemas.TemplateRenderArtifact.properties.resolved_orientation.description
Optional bottom-center anchor direction when the surface contains exactly one resolved exact image slot.

# components.schemas.TemplateOutputContractSlot.properties.key.description
Opaque runtime binding key. This is the only field used to submit values.

# components.schemas.TemplateOutputContractSlot.properties.ordinal.description
Revision-local presentation order, not an identity.

# components.schemas.TemplateOutputContractSlot.properties.suggested_semantic_key.description
Platform vocabulary suggestion only; it is never a runtime lookup alias.

# components.schemas.OrderLine.properties.texts.description
Text values keyed by the selected product's published semantic slots. Each slot may occur at most once; preserve intentional whitespace exactly.

# components.schemas.CustomerContact.description
For quote and submit API routes, at least email or phone is required.

# components.schemas.ShippingService.description
Required domestic US delivery service. The server freezes the exact deterministic provider shipping quote before payment; a service can be unavailable when provider eligibility, a one-day zone result, or required provider cost evidence is unavailable.

# components.schemas.QuoteAPIOrderRequest.properties.provider_id.description
Optional explicit provider. It takes precedence over event and account defaults.

# components.schemas.QuoteAPIOrderRequest.properties.event_id.description
Optional opaque event/cohort ID. Its saved provider selection applies when provider_id is omitted.

# components.schemas.SubmitAPIOrderRequest.properties.integration_source.description
Analytics attribution only; it cannot alter authorization, pricing, settlement, or provider selection.

# components.schemas.APIAccountOwner.description
Exactly one reference is present: studio_id for studio accounts or individual_owner_user_id for individual accounts.

# components.schemas.CreateAPIAccountRequest.properties.studio_id.description
Required only when owner_type is studio.