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

# Transfer a Persona operator

> Submit the DNS-attested, two-party Persona transfer

Submit a prepared Persona transfer with the new operator's acceptance signature and the current controller's final authorization signature.

The final request repeats the verified intent and attestation so the Directory can reconstruct the exact signed payload. `acceptance_payload` may be included but is not required at this step.

## Request

Include the complete verified transfer intent, including the required echoed `verification_expires_at`, plus `attestor`, `attestation_signature`, `new_operator_signature`, and these fields:

<ParamField path="persona" type="string" required>
  Persona being transferred.
</ParamField>

<ParamField body="challenge_id" type="string" required>
  Verified, unused transfer challenge.
</ParamField>

<ParamField body="canonical_payload" type="string" required>
  Exact payload returned by the prepare endpoint.
</ParamField>

<ParamField body="signature" type="string" required>
  Current Persona-controller signature over the decoded `canonical_payload` bytes.
</ParamField>

<RequestExample>
  ```bash Request theme={null}
  curl --request PUT \
    --url "https://directory.example.com/personas/example.com/operator" \
    --header "Content-Type: application/json" \
    --data '{
      "action": "transfer_persona",
      "persona": "example.com",
      "current_operator_did": "did:openpayload:1111111111111111111111",
      "new_operator_did": "did:openpayload:2222222222222222222222",
      "new_controller_keys": [
        "did:openpayload:2222222222222222222222#keys-1"
      ],
      "new_controller_threshold": 1,
      "delivery_constraints": {
        "requested_cache_seconds": 86400,
        "max_http_envelope_bytes": 26214400,
        "max_unchunked_message_bytes": 16777216,
        "max_chunk_bytes": 2097152,
        "max_replicas": 2
      },
      "challenge_id": "<challenge-id>",
      "verification_expires_at": 1796083200000,
      "new_operator_signer_key_id": "did:openpayload:2222222222222222222222#keys-1",
      "nonce": "<current-operator-nonce>",
      "valid_until": "<epoch-milliseconds>",
      "signer_key_id": "did:openpayload:1111111111111111111111#keys-1",
      "attestor": "0x<directory-attestor-account>",
      "attestation_signature": "0x<directory-attestation-signature>",
      "new_operator_signature": "<base64-new-operator-signature>",
      "canonical_payload": "0x<current-controller-authorization-payload>",
      "signature": "<base64-current-controller-signature>"
    }'
  ```
</RequestExample>

## Response

```json 202 Response theme={null}
{
  "status": "accepted",
  "persona": "example.com",
  "current_operator_did": "did:openpayload:1111111111111111111111",
  "new_operator_did": "did:openpayload:2222222222222222222222",
  "extrinsic": "apply_persona_with_proof",
  "operation": "transfer_persona",
  "tx_hash": "<transaction-hash>"
}
```

`202 Accepted` confirms submission, not finalization. Read the Persona until the new `operator_did`, controller set, DNS timestamps, constraints, and revision are finalized.

Transfer clears the previous Persona policy. Publish a new Persona policy under the new controller if one is required. If `delivery_constraints` was omitted from the transfer intent, the Persona has no Persona-specific constraints and delivery falls through to the remaining effective constraints.

## Straight to the point

```http theme={null}
PUT /personas/{persona}/operator
```

* Requires fresh DNS verification, new-operator acceptance, and current-controller authorization
* Consumes the transfer challenge on accepted submission
* Replaces the operator and controller set
* Clears the previous Persona policy


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