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

# Profile

> Fill a JSON Schema about the person from their camera roll.

`profile(schema:)` fills a JSON Schema you write with what the person's life says: their favorite cuisine, their home city, their trips. Each filled field comes with the photos behind it.

```swift theme={null}
let schema = Data("""
{
  "type": "object",
  "properties": {
    "favorite_cuisine": { "type": "string", "description": "The cuisine they eat most often" },
    "cuisines": { "type": "array", "items": { "type": "string" }, "description": "Cuisines they eat, most often first" },
    "dining_out": { "type": "string", "enum": ["rarely", "weekly", "several times a week"] },
    "favorite_restaurant": { "type": "string", "description": "The restaurant they return to most" },
    "drinks_coffee": { "type": "boolean" }
  }
}
""".utf8)

let profile = try await Rollup.shared.profile(schema: schema)
```

It works like [`query`](/guides/query): an agent on Rollup's server calls tools that run on the iPhone, and only their text results leave the device.

## What comes back

<ResponseField name="json" type="Data">
  The filled profile as JSON, in your schema's shape exactly. Every field is present. A field is `null` when the person's life does not say, never a guess. Use `value` to read it as a `JSONValue`.
</ResponseField>

<ResponseField name="evidence" type="[String: [String]]">
  The PhotoKit local identifiers behind each filled field, keyed by JSON Pointer, such as `/favorite_restaurant`.
</ResponseField>

<ResponseField name="refused" type="[String: String]">
  Fields Rollup would not fill, keyed by JSON Pointer, with the reason. See [Sensitive fields](#sensitive-fields).
</ResponseField>

```json theme={null}
{
  "json": {
    "favorite_cuisine": "Japanese",
    "cuisines": ["Japanese", "Italian", "Mexican"],
    "dining_out": "weekly",
    "favorite_restaurant": null,
    "drinks_coffee": true
  },
  "evidence": {
    "/favorite_cuisine": ["5A1C...-001", "9F3B...-001"],
    "/drinks_coffee": ["C27E...-001"]
  },
  "refused": {}
}
```

## Writing a schema

Rollup accepts a subset of JSON Schema:

* The root is an object schema: `"type": "object"` with `properties`.
* Keywords: `type`, `properties`, `required`, `items`, `enum`, `description`, `title`, `additionalProperties` (only `false`) and `$schema`. Anything else is refused.
* Types: `string`, `number`, `integer`, `boolean`, `object` and `array`.
* An object needs at least one property. An array needs an `items` schema.
* An `enum` lists 1 to 200 values of the field's type.
* At most 5 levels of nesting, 100 fields in all, and 32 KB of JSON.

Every field may come back `null`, whatever your schema says about `required`. Inside an array, items are values: a list Rollup cannot fill is `null`, not a list of nulls.

Write a `description` for any field whose name does not say exactly what you want. The agent reads it.

Data that is not a JSON object throws `RollupError` with code `invalidSchema`. A schema outside this subset is refused by the server with the same code: the error's `serverCode` is `invalid_schema`, and its message names the first problem and where it is, such as `/trips: an array takes items, not properties or enum.`

## Sensitive fields

Rollup does not fill fields about a person's health, religion, sexuality, ethnicity or race, politics, or children. A field is refused when its name, title, description or allowed values use those words, before the agent sees the schema. The agent may refuse more fields it judges sensitive.

A refused field is `null` in the profile, has no evidence, and is listed in `refused` with a reason such as "Rollup does not fill fields about health."

## Limits

* A profile takes a few seconds to about 20 seconds and needs a network connection.
* Each step counts toward your app's rate limits and monthly token budget. See [Limits and budgets](/guides/limits-and-budgets).

<Warning>
  Before your app calls `profile`, tell the person what you will learn about them and that text derived from their photos is sent to Rollup and its model provider. Get their permission. See [Privacy and App Review](/guides/privacy).
</Warning>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.