> ## Documentation Index
> Fetch the complete documentation index at: https://docs.photalabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Best practices

> Tips for getting the best results from the Phota API

export const MAX_PROFILE_PHOTOS = 50;

export const MIN_PROFILE_PHOTOS = 10;

***

## Choose the right training photos

Profile quality directly affects every edit and generation you run. Aim for {MIN_PROFILE_PHOTOS}–{MAX_PROFILE_PHOTOS} reference
photos that cover a range of conditions:

* **Clear, well-lit faces** -- the subject's face should be easy to see in every photo.
* **High resolution** -- use 1K+ images. Avoid small crops, heavy compression, or noisy shots.
* **Diverse expressions** -- include neutral, smiling, frowning, and surprised faces.
* **Multiple angles** -- front-facing, slight left/right turns, and at least one profile view.
* **Varied lighting** -- mix indoor, outdoor, sunny, and overcast conditions.
* **Group shots are OK** -- as long as the intended subject's face is clearly visible.

Avoid extreme poses, motion blur, heavy occlusion (sunglasses covering most of the face), and dark or noisy images.

<Tip>
  See the [Profiles guide](/guides/profiles#tips-for-best-results) for visual examples of good and bad training photos.
</Tip>

***

## Scope `profile_ids` to the current end-user

The API only considers profiles for identify preservation that are explicitly included in each request.
It never silently matches against other profiles in your account -- if you don't pass any, no identity preservation is applied.

Your developer account holds profiles for all of your users, but each request should only include the profiles
belonging to the end-user whose photo is being processed.

<Tip>
  A profile can be passed via the `profile_ids` field **or** inline with `[[profile_id]]` in the prompt — you don't need
  both. If you do list the same ID in both places it's harmless (the API merges them), but usually one is enough. See
  [Referencing profiles in requests](/guides/profiles#referencing-profiles-in-requests) for when each is best.
</Tip>

```json theme={null}
{
  "prompt": "Add [[abc123]] to the family picture",
  "images": ["https://example.com/family.jpg"],
  "profile_ids": ["def456", "ghi789", "jkl012"]
}
```

Here `[[abc123]]` is picked up from the prompt and the other three IDs are additional candidates in case the API needs
to recognize anyone already in the input photo.

The fewer profiles you pass, the easier it is for our system to match the right ones. Passing your entire
account's profile list forces the model to sort through unrelated identities, which can hurt accuracy.

***

## Write descriptive prompts

The more specific your prompt, the better the result. Two principles help:

1. **Say what to change.** Be explicit about the transformation you want -- pose, expression, background, style, lighting.
2. **Say what to keep.** Tell the model what should stay the same so it doesn't alter things you care about.

```json theme={null}
{
  "prompt": "Make [[abc123]] cross their arms and look directly at the camera. Keep the background, lighting, and outfit unchanged.",
  "images": ["https://example.com/photo.jpg"],
  "profile_ids": ["abc123"]
}
```

Vague prompts like "make it better" give the model too much freedom. Instead, describe the specific change:
"Brighten the lighting on the subject's face and remove the shadow on the left side."

***

## Use `[[profile_id]]` in prompts for generation and multi-person scenes

For edit and enhance requests, the `profile_ids` field tells the API which identities are available to draw from. The
`[[profile_id]]` prompt syntax helps referring to a specific subject in the input photo.

**When you need it:**

* **Generation** -- the `/generate` endpoint does not accept `profile_ids`. Inline `[[...]]` references in the prompt
  are the only way to specify which subjects to generate.

**Generation example:**

```json theme={null}
{
  "prompt": "A photo of [[abc123]] and [[def456]] sitting across from each other at a cafe",
  "num_output_images": 2
}
```

**Edit example:**

```json theme={null}
{
  "prompt": "Add [[def456]] to this group shot",
  "images": ["https://example.com/group.jpg"],
  "profile_ids": ["abc123","ghi789"]
}
```

For single-person edits where the subject is already in the input photo, `profile_ids` alone is usually enough --
our system matches the face in the photo to the provided profiles automatically.

<Tip>
  For edits, profile IDs referenced with `[[...]]` in the prompt are automatically merged into `profile_ids`, so you
  don't need to list them in both places (but it doesn't hurt if you do).
</Tip>

***

## Use aspect ratio and resolution controls

You can set `aspect_ratio` and `resolution` on every edit and generate request.

Use these when:

* You need a specific aspect ratio (e.g. `9:16` for stories, `1:1` for profile pictures).
* You want 4K output resolution for higher detail.

```json theme={null}
{
  "prompt": "Convert this group photo into a cinematic wide shot with dramatic lighting",
  "images": ["https://example.com/group.jpg"],
  "profile_ids": ["abc123", "def456"],
  "aspect_ratio": "16:9",
  "resolution": "4K"
}
```

***

## Generate multiple variations

Output is non-deterministic -- the same prompt can produce noticeably different results each time. Set
`num_output_images` to 2-4 and let the end-user pick the best one.

```json theme={null}
{
  "prompt": "Professional headshot of [[abc123]] in a modern office",
  "num_output_images": 4
}
```

This is especially useful for generation, where there is no input image anchoring the composition. Multiple variations
give a much better chance of landing on a great result in a single API call.

***

## Choose output format and response mode

Every edit, generate, and enhance request accepts `output_format` and `response_mode` parameters.

**`output_format`** controls the image encoding:

* `"jpg"` (recommended) — significantly smaller than PNG, reducing response size and latency. Best for most use cases.
* `"png"` — lossless quality. Use when you need transparency support or when re-encoding artifacts would accumulate.

**`response_mode`** controls how images are delivered:

* `"bytes"` (default) — base64-encoded image data in the `images` field. No data is stored server-side.
* `"urls"` — signed CDN download URLs (24-hour expiry) in the `download_urls` field. Use for mobile clients, bandwidth-constrained environments, or when you only need a URL to display or store.

Each mode populates its respective field and leaves the other empty — the response never contains both.

```json theme={null}
{
  "prompt": "Professional headshot of [[abc123]]",
  "output_format": "jpg",
  "response_mode": "urls"
}
```

<Warning>
  4K PNG images in `response_mode: "bytes"` exceed the maximum response size and will be rejected with a
  400 error. To use 4K resolution, switch to `response_mode: "urls"`, use `output_format: "jpg"`, or lower the
  resolution.
</Warning>

***

## Debug identity issues with `known_subjects`

Every edit, generate, and enhance response includes a `known_subjects` field that reports which profiles our system
successfully recognized and rendered:

```json theme={null}
{
  "images": ["/9j/4AAQ..."],
  "download_urls": [],
  "known_subjects": {
    "counts": {
      "abc123": 1,
      "def456": 1
    }
  }
}
```

The `counts` dict maps each `profile_id` to the number of times that subject appeared across all output images.

**If a subject looks wrong in the output, check `known_subjects` first.** If their `profile_id` is missing from
`counts`, our system could not figure out how to preserve that subject's identity. This usually means:

* The profile was not included in `profile_ids` (for edit/enhance) or not referenced with `[[...]]` in the prompt (for generate).
* The subject in the input photo was difficult to recognize, e.g., due to occlusion, low resolution, or poor lighting.
* Too many profiles were passed in `profile_ids`, making it harder for our system to match the right one.
* The profile is still training (`IN_PROGRESS`) or failed (`ERROR`).

When the `profile_id` *is* present in `counts` but the result still looks off, the issue is more likely prompt-related.
Try being more specific about the subject's placement, or generate additional variations.

***

## Next steps

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/api/quickstart">
    Walk through the full workflow from authentication to your first edit.
  </Card>

  <Card title="Profiles guide" icon="user-group" href="/guides/profiles">
    Deep-dive into profile creation, image requirements, and the \[\[profile\_id]] syntax.
  </Card>
</CardGroup>
