# PATINA · Material API

> 타일링 가능한 이미지와 PBR 맵을 출력하며 선택적 img2img 및 인페인팅을 지원하는 텍스트-텍스처 생성기

프롬프트에서 타일링 가능한 텍스처를 생성하고 PBR 맵인 basecolor, normal, roughness, metalness 및 height를 예측합니다. `tiling_mode`로 양방향, 가로 또는 세로 타일링을 선택하고, `upscale_factor`를 0, 2 또는 4로 설정해 맵을 확대합니다. `image_url`을 전달하면 이미지-이미지가 활성화되고, `mask_url`을 추가하면 인페인팅이 활성화됩니다. 요청당 최대 4개의 이미지가 제공됩니다.

- Model id: `patina/material`
- Made by: Open model
- Category: Text to Image
- Output: image
- Price per run: from $0.08 / run (cheapest run $0.08 (80 API credits))
- Run: `POST https://api.doitong.com/v1/run/patina/material`
- Quote: `POST https://api.doitong.com/v1/quote/patina/material`
- Docs page: https://doitong.com/ko/developers/models/patina/material

## Pricing

Price: **from $0.08 / run** (the lowest tier; the quote prices your exact input). Price per run: the input files are measured before the run (length, resolution, frame rate). The quote measures the same files and is exactly what the run charges.

The full example input below costs $0.08 = 80 API credits (1 run × $0.08).

Prices are the upstream price in USD, paid from the API balance in API credits (1000 API credits = 1 USD). `POST https://api.doitong.com/v1/quote/patina/material` with the same JSON body returns the exact price for that input; the quote is exactly what a run charges. Invalid input is never charged and failed or canceled requests are refunded automatically.

## Input parameters

Send either the canonical name or the native field name (not both). Canonical names are the same across models.

| Parameter | Canonical name | Type | Required | Default | Allowed values / range | Description |
|---|---|---|---|---|---|---|
| `prompt` |  | string | yes |  |  | 생성할 재질 또는 텍스처의 텍스트 설명입니다. |
| `image_size` |  | object {width, height} \| enum (string) | no | `square_hd` | `square_hd`, `square`, `portrait_4_3`, `portrait_16_9`, `landscape_4_3`, `landscape_16_9` | 결과 텍스처의 픽셀 크기입니다. |
| `num_inference_steps` |  | integer | no | `8` | 1 – 8 | 텍스처 생성에 사용되는 노이즈 제거 단계 수입니다. |
| `seed` |  | integer \| null | no |  |  | 생성 결과를 재현할 수 있게 하는 무작위 시드입니다. |
| `num_images` | `num_outputs` | integer | no | `1` | 1 – 4 | 생성할 텍스처 이미지 수입니다. |
| `enable_prompt_expansion` |  | boolean | no | `true` |  | 세부 정보를 추가하는 LLM 기반 프롬프트 확장을 활성화합니다. |
| `enable_safety_checker` |  | boolean | no | `true` |  | 생성된 이미지의 안전성 검사를 활성화합니다. |
| `tiling_mode` |  | enum (string) | no | `both` | `both`, `horizontal`, `vertical` | 타일링 방향입니다. 'both'는 전방향 타일링, 'horizontal' 또는 'vertical'을 사용합니다. |
| `tile_size` |  | integer | no | `128` | 32 – 256 | 잠재 공간 타일 크기입니다. 64는 512px, 128은 1024px를 나타냅니다. 타일링되는 각 축에서 생성 이미지의 크기가 자동 상한을 설정합니다. |
| `tile_stride` |  | integer | no | `64` | 16 – 128 | 잠재 공간 타일 간 스트라이드를 설정합니다. 자동 제한으로 유효 타일 크기의 절반을 초과하지 않습니다. |
| `image_url` | `image` | string (image URL) \| null | no |  |  | 소스 이미지 URL입니다. mask_url이 함께 제공되면 인페인팅에 사용하고, 그렇지 않으면 이미지 간 처리에 사용합니다. |
| `mask_url` | `mask` | string (image URL) \| null | no |  |  | 필수 image_url과 함께 제공되는 인페인팅 마스크 URL입니다. 마스크는 검은색 영역을 그대로 유지하고 흰색 영역을 다시 생성합니다. |
| `strength` |  | number | no | `0.6` | ≤ 1, > 0 | image_url을 통해 제공된 이미지에만 적용되는 변환 강도이며, 그 외에는 사용되지 않습니다. |
| `maps` |  | array of enum (string) | no | `["basecolor","normal","roughness","metalness","height"]` |  | 예측에 선택되는 PBR 맵으로, 기본값은 5개 모두 선택입니다. 아무것도 선택하지 않으면 PBR 추정을 완전히 건너뜁니다. |
| `upscale_factor` |  | enum (integer) | no | `0` | `0`, `2`, `4` | 예측된 PBR 맵에 적용되는 SeedVR 심리스 업스케일링 배율이며, 기본 텍스처는 원래 해상도로 유지됩니다. 2는 2배, 4는 4배 해상도이며 0은 업스케일링을 비활성화합니다. |
| `output_format` |  | enum (string) | no | `png` | `jpeg`, `png`, `webp` | 출력 텍스처 및 PBR 맵의 이미지 파일 형식입니다. |

File parameters (`image`, `mask`) take a public `https://` URL, a `data:` URI up to 10 MB, or the `file_url` of an upload from `POST /files`.

## Example input

Required parameters only:

```json
{
  "prompt": "A red fox trots through fresh snow at sunrise, soft golden light, shallow depth of field"
}
```

A fuller example:

```json
{
  "prompt": "A red fox trots through fresh snow at sunrise, soft golden light, shallow depth of field"
}
```

## Run it

Set `DOITONG_API_KEY` to a key from https://doitong.com/developers/dashboard#keys. `?wait=20` returns the finished request in the same call when it is ready within 20 seconds; otherwise poll `GET /requests/{id}` (it also accepts `?wait=`), or pass `webhook_url`.

### curl

```bash
# Run the model; wait up to 20 s for the finished result in the same call
curl -X POST "https://api.doitong.com/v1/run/patina/material?wait=20" \
  -H "Authorization: Bearer $DOITONG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "A red fox trots through fresh snow at sunrise, soft golden light, shallow depth of field"
  }'

# Still "queued" or "running"? Poll with the id from the response:
curl "https://api.doitong.com/v1/requests/REQUEST_ID?wait=20" \
  -H "Authorization: Bearer $DOITONG_API_KEY"
```

### JavaScript

```javascript
const API = "https://api.doitong.com/v1";
const headers = {
  "Authorization": "Bearer " + process.env.DOITONG_API_KEY,
  "Content-Type": "application/json",
};

// Run the model; wait up to 20 s for the finished result in the same call
let res = await fetch(API + "/run/patina/material?wait=20", {
  method: "POST",
  headers,
  body: JSON.stringify({
    "prompt": "A red fox trots through fresh snow at sunrise, soft golden light, shallow depth of field"
  }),
});
let request = await res.json();
if (!res.ok) throw new Error(request.error.code + ": " + request.error.message);

// Not finished yet: long-poll until it is
while (request.status === "queued" || request.status === "running") {
  res = await fetch(API + "/requests/" + request.id + "?wait=20", { headers });
  request = await res.json();
}
if (request.status !== "succeeded") throw new Error(JSON.stringify(request.error));
console.log(request.outputs.map((o) => o.url), request.cost.credits + " API credits ($" + request.cost.usd + ")");
```

### Python

```python
import os
import requests

API = "https://api.doitong.com/v1"
headers = {"Authorization": "Bearer " + os.environ["DOITONG_API_KEY"]}

payload = {
    "prompt": "A red fox trots through fresh snow at sunrise, soft golden light, shallow depth of field",
}

# Run the model; wait up to 20 s for the finished result in the same call
r = requests.post(API + "/run/patina/material", params={"wait": 20}, json=payload, headers=headers)
request = r.json()
if not r.ok:
    raise RuntimeError(request["error"]["code"] + ": " + request["error"]["message"])

# Not finished yet: long-poll until it is
while request["status"] in ("queued", "running"):
    request = requests.get(API + "/requests/" + request["id"], params={"wait": 20}, headers=headers).json()
if request["status"] != "succeeded":
    raise RuntimeError(request["error"])
print([o["url"] for o in request["outputs"]], request["cost"]["credits"], "API credits", "$" + request["cost"]["usd"])
```

### MCP

The MCP server at `https://api.doitong.com/v1/mcp` exposes the tools `search_models`, `get_model`, `quote`, `run`, `get_request`, `cancel_request`, `list_requests`, `create_upload` and `get_account`. A `run` call for this model:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "run",
    "arguments": {
      "model_id": "patina/material",
      "input": {
        "prompt": "A red fox trots through fresh snow at sunrise, soft golden light, shallow depth of field"
      },
      "wait_seconds": 20
    }
  }
}
```

## Response

Every call returns a request object. `status` is one of `queued`, `running`, `succeeded`, `failed`, `canceled`. `outputs` lists the generated files with URLs on our storage (kept forever, or 7 days with `?storage=temporary`; `storage` says which); `output` is the model's own result object with the same URLs.

```json
{
  "id": "req_8k2m4q7x1z9c3v5b6n0p2r4t",
  "object": "request",
  "model": "patina/material",
  "status": "succeeded",
  "created_at": "2026-10-20T12:00:00Z",
  "started_at": "2026-10-20T12:00:02Z",
  "completed_at": "2026-10-20T12:00:09Z",
  "queue_position": null,
  "cost": {
    "credits": 80,
    "usd": "0.08",
    "charged": 80,
    "refunded": 0
  },
  "input": {
    "prompt": "A red fox trots through fresh snow at sunrise, soft golden light, shallow depth of field"
  },
  "output": {
    "images": [
      {
        "url": "https://content.doitong.com/dev-api/2026/10/20/req_8k2m4q7x1z9c3v5b6n0p2r4t/0-output.jpeg",
        "content_type": "image/jpeg",
        "file_name": "0-output.jpeg",
        "file_size": 1843200,
        "width": 1024,
        "height": 768
      }
    ],
    "seed": 42,
    "prompt": "string",
    "timings": {}
  },
  "outputs": [
    {
      "type": "image",
      "url": "https://content.doitong.com/dev-api/2026/10/20/req_8k2m4q7x1z9c3v5b6n0p2r4t/0-output.jpeg",
      "content_type": "image/jpeg",
      "file_size": 1843200,
      "width": 1024,
      "height": 768,
      "stored": true
    }
  ],
  "error": null,
  "metrics": {
    "inference_seconds": 6.8
  },
  "urls": {
    "self": "https://api.doitong.com/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t",
    "cancel": "https://api.doitong.com/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t/cancel"
  }
}
```

### Output fields (`output`)

| Field | Type | Description |
|---|---|---|
| `images` | array of any | 출력 이미지에 PATINA가 예측한 PBR 재질 맵과 z-image가 생성한 타일 가능 텍스처가 포함됩니다. |
| `seed` | integer | 텍스처 생성 시 적용되는 시드입니다. |
| `prompt` | string | 확장된 내용이 포함된 텍스처 생성 프롬프트입니다. |
| `timings` | object | 전체 프로세스의 초 단위 타이밍 내역입니다. |

## Related models

- [PATINA](https://doitong.com/developers/models/patina.md) (`patina`): from $0.0225 / run of input image
- [PATINA · Material · Extract](https://doitong.com/developers/models/patina/material/extract.md) (`patina/material/extract`): from $0.17 / run
- [FLUX.1 \[dev\]](https://doitong.com/developers/models/flux/dev.md) (`flux/dev`): $0.025 / megapixel
- [FLUX.1 \[schnell\]](https://doitong.com/developers/models/flux/schnell.md) (`flux/schnell`): $0.003 / megapixel
- [FLUX.2 \[dev\]](https://doitong.com/developers/models/flux-2.md) (`flux-2`): $0.012 / megapixel
- [FLUX.2 \[pro\]](https://doitong.com/developers/models/flux-2-pro.md) (`flux-2-pro`): $0.015 / megapixel of output image
- [GPT Image 2.5 Text to Image](https://doitong.com/developers/models/openai/gpt-image-2.5/flare/text-to-image.md) (`openai/gpt-image-2.5/flare/text-to-image`): from $0.008 / image
- [Ideogram V4.5](https://doitong.com/developers/models/ideogram/v4.5.md) (`ideogram/v4.5`): from $0.03 / image

## Links

- HTML page: https://doitong.com/developers/models/patina/material
- All models and guides for AI agents: https://doitong.com/developers/llms.txt
- OpenAPI 3.1 with this model's typed request body: https://doitong.com/developers/openapi.json?model=patina/material
- Errors: https://doitong.com/developers/docs/errors
- Model details as JSON: https://api.doitong.com/v1/models/patina/material
