API v1 preview

# Replace a model file

`POST /api/v1/models/{model_id}/revisions`

## Overview

Append an immutable source-file revision to an owned model and restart processing. Send If-Match from GetModel to guard against concurrent edits; omit for last-write-wins. Idempotency-Key is optional, retained for 24 hours, and replays the original response snapshot. The model ID stays the same. Repair coverage remains attached to the original file revision.

Requires `models:write`.

[Model edits and revisions guide](https://ottomfg.com/docs/edit-models.md)

[Errors and retries](https://ottomfg.com/docs/errors.md)

Request

bash

```
# Requires models:write; upload the replacement first using files:write.
# Save only source.file_id in model-replacement.json; GET the model's ETag.
# Save REVISION_REQUEST_KEY once per intended replacement, before sending.
: "${MODEL_ETAG:?Set the saved ETag, including its quotes}"
: "${REVISION_REQUEST_KEY:?Set a saved key for this replacement}"
curl --fail-with-body --max-time 30 --request POST \
  "${API_BASE_URL%/}/api/v1/models/$MODEL_ID/revisions" \
  --header "Authorization: Bearer $OTTOMFG_API_KEY" \
  --header "If-Match: $MODEL_ETAG" \
  --header "Idempotency-Key: $REVISION_REQUEST_KEY" \
  --header "Content-Type: application/json" \
  --data-binary @model-replacement.json
# Retry the saved key, body and ETag after a timeout, within 24 hours.
# A replay returns the original replacement response; GET for current state.
# A new request with a stale If-Match returns 412 precondition_failed.
```

Set API_BASE_URL, OTTOMFG_API_KEY and MODEL_ID. Save the write body and GET ETag as MODEL_ETAG for If-Match. The replacement example also uses REVISION_REQUEST_KEY for retries. See the guide before sending. History reads need no body or key.

[Edit setup and recovery](https://ottomfg.com/docs/edit-models.md)

## Parameters

`model_id` path · required

Immutable model ID: MD- followed by eight uppercase Crockford Base32 characters. Use this same ID in the website, URLs and API; pass it unchanged.

string

`Idempotency-Key` header · optional

Account, method and path scoped retry key, retained for 24 hours from first use. Same body replays the original successful status and body. A changed body returns 409 idempotency_key_reused; an in-flight request returns 409 idempotency_request_in_progress with Retry-After. Retry transient failures with the same key and body.

string

`If-Match` header · optional

ETag from GetModel. The edit applies only while that version is current; otherwise 412 precondition_failed. Omit for last-write-wins. A replay with the same Idempotency-Key returns the original response even if the model has since changed.

string

## Request body

application/json

`source` object · required

Reference to an uploaded geometry file and its supporting assets. One file can back multiple models in the same account. Set print size explicitly using longest_dimension_mm.

**source fields**

`file_id` string · required

Unique, server-generated file ID. Treat it as an opaque reference.

Min length: 37 · Max length: 37

## Responses

Current model after replacement.

200 response

JSON

```
{
  "id": "MD-739YQ549",
  "file_revision": 2,
  "source": {
    "file_id": "file_7c82bd3e319b4bb099310d54a761879e"
  },
  "name": "Wedding figurine",
  "created_at": "2026-09-18T18:00:00.000000Z",
  "updated_at": "2026-09-30T00:01:00.000000Z",
  "status": "processing",
  "status_reasons": [
    {
      "code": "inspection_pending",
      "message": "Mesh inspection is running."
    }
  ],
  "preview": {
    "status": "pending"
  },
  "longest_dimension_mm": 100,
  "mesh_check": {
    "status": "pending"
  },
  "print_check": {
    "status": "pending"
  },
  "repair": {
    "required": false,
    "applied": false,
    "reason": null,
    "status": "not_applied",
    "fee": 0,
    "covered_by_order_id": null
  },
  "progress": {
    "stage": "queued"
  },
  "volume": null,
  "estimated_weight_g": null
}
```

Returns [the Model object](https://ottomfg.com/docs/model-object.md).

**Response headers**

`X-Request-ID`

Request identifier for support. Send X-Request-ID with 8–64 ASCII letters, digits or hyphens to reuse that value; otherwise the server generates a UUID4 hex value. Include the returned X-Request-ID in support requests. Do not put secrets or account IDs in this value.

`Idempotent-Replayed`

Present when the original successful response is replayed.

## Errors

| HTTP | Code | What to do |
| --- | --- | --- |
| 400 Bad Request | `file_not_found` | No file with this ID exists in the account, or it expired before a model used it. Register and upload the file again. |
| 401 Unauthorized | `unauthenticated` | The API key is missing, invalid or revoked. Send a valid business API key in Authorization: Bearer. |
| 403 Forbidden | `permission_denied` | The key lacks the endpoint's scope, or payments lack spending consent. Check the scope listed on the endpoint. |
| 404 Not Found | `model_not_found` | No model with this ID exists in the account, or it was deleted. Check the ID. |
| 409 Conflict | `idempotency_key_reused` | This Idempotency-Key was already used with a different body. Retry the original body, or use a new key for a new operation. |
| 409 Conflict | `idempotency_request_in_progress` | A request with this Idempotency-Key is still running. Wait Retry-After seconds, then retry the same key and body. |
| 412 Precondition Failed | `precondition_failed` | The model changed since you read its ETag. Read it again, review the change, then retry with the new ETag in If-Match. |
| 413 Content Too Large | `request_too_large` | The JSON body is over this endpoint's size limit. Send a smaller body. |
| 415 Unsupported Media Type | `unsupported_media_type` | The body is not JSON. Send Content-Type: application/json. |
| 429 Too Many Requests | `resource_exhausted` | A rate or account limit was reached. Wait at least Retry-After seconds, then retry. |
| 500 Internal Server Error | `internal` | The server failed unexpectedly. Retry with backoff; contact support with X-Request-ID if it persists. |
| 503 Service Unavailable | `unavailable` | A required service is briefly unavailable. Retry with backoff, reusing the same Idempotency-Key. |

[Idempotent requests](https://ottomfg.com/docs/idempotency.md)

API v1 preview

Source: https://ottomfg.com/docs/replace-model-file
