> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.morphiaone.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.morphiaone.ai/_mcp/server.

# API overview

> **Info**
>
> **Release status.** API `1.0.0-rc.1` is a release candidate: request and response shapes may still change before the stable release. SDK `0.2.2` is published as a Developer Preview (`@morphiaone/sdk` on npm and `morphiaone` on PyPI).

## Base URL and authentication

```text
https://api.morphiaone.ai
```

Every operation takes an API key in the `X-API-Key` header. Keys are server-side
secrets; see [Authentication](/getting-started/authentication) and
[Get access](/getting-started/access).

## One request pattern

Upload an image once as an **Asset**, submit a product request that names its Asset id,
then follow the returned **Job**. A succeeded Job carries a typed output. Result images
are Assets fetched through the API before they expire.

```text
POST /v1/assets                    raw image bytes in, an Asset out
      |
      | asset_id
      v
POST /v1/skin/analyses             typed JSON, answers a Job
POST /v1/makeup/try-ons            typed JSON, answers a Job
POST /v1/hair/try-ons              typed JSON, answers a Job
      |
      v
GET  /v1/jobs/{job_id}             queued -> running -> succeeded | failed | cancelled
      |
      v
GET  /v1/assets/{asset_id}/content result image bytes
```

## Operations

| Operation                           | Purpose                                                                     |
| ----------------------------------- | --------------------------------------------------------------------------- |
| `POST /v1/assets`                   | Upload an input image.                                                      |
| `GET /v1/assets`                    | List your Assets, newest first.                                             |
| `GET /v1/assets/{asset_id}`         | Read Asset metadata.                                                        |
| `GET /v1/assets/{asset_id}/content` | Download result image bytes.                                                |
| `DELETE /v1/assets/{asset_id}`      | Delete an input Asset and erase its bytes.                                  |
| `POST /v1/skin/analyses`            | Submit Skin Analysis.                                                       |
| `POST /v1/makeup/try-ons`           | Submit Makeup Try-On.                                                       |
| `POST /v1/hair/try-ons`             | Submit Hair Color Try-On; the hair is found for you, or pass your own mask. |
| `GET /v1/jobs`                      | List your Jobs, newest first.                                               |
| `GET /v1/jobs/{job_id}`             | Read the state and output of a Job.                                         |
| `POST /v1/jobs/{job_id}/cancel`     | Cancel a Job that has not started processing.                               |
| `DELETE /v1/jobs/{job_id}`          | Delete a finished Job and its result Assets.                                |
| `GET /v1/usage`                     | Read accepted job counts by UTC day and operation.                          |
| `GET /v1/credits/balance`           | Read your account's credit balance.                                         |

Listing, cancel, delete and the credit balance are enabled per environment. Where one is
not enabled for yours, it answers `404` as an unknown path does. Signed
[webhooks](/concepts/webhooks) for `job.succeeded`, `job.failed`, `job.cancelled` and
`test.ping` are documented in the same reference.

## Contract details

* Upload input images as raw bytes and reference their Asset ids in product requests.
* Every product submission requires an `Idempotency-Key`. Repeating the same key and
  body replays the original Job; reusing a key with a changed body returns a conflict.
* A submit response means the Job was accepted, not that processing succeeded. Poll
  until the Job is terminal, then branch on its typed output or error.
* The Job output is an open union. Ignore unknown fields and preserve an unknown output
  type rather than assuming every response shape is known to the client.
* `error.code` is the machine-readable failure identifier. Every error also carries
  `doc_url` and `retryable`; `error.details` carries field-level validation information
  when relevant.

The [Assets](/concepts/assets), [Jobs](/concepts/jobs),
[Idempotency](/concepts/idempotency), and [Errors](/concepts/errors) guides explain
integration behavior. The endpoint reference in this section is generated from the
OpenAPI contract the service itself serves, so it cannot describe an operation the API
does not have.

## Use an SDK or REST

Start with the [TypeScript SDK](/sdks/typescript) or [Python SDK](/sdks/python). Both
packages handle authentication headers, Asset upload, idempotency keys, retries, job
polling, and typed outputs. Use [REST onboarding](/rest-api/onboarding) if you need to
make HTTP calls directly.