---
title: "Update"
method: PUT
path: "/contacts/{id}"
tags: ["contacts"]
---

# Update

`PUT /contacts/{id}`

## Request

- Base URL: `https://api.instruxi.dev/api/v1/enforcer`
- URL: `https://api.instruxi.dev/api/v1/enforcer/contacts/{id}`
- Auth: one of:
  - API key in header `Authorization`
  - API key in header `X-API-Key`

Partial update of the caller's own contact. custom_wallet_address may only be set/cleared on a CUSTOM contact — 400 on a linked one, whose payable address is always that account's own active wallet. For both custom_wallet_address and custom_avatar_url, send "" to explicitly clear the field; omit it to leave the stored value unchanged.

## Path parameters

- `id` string, required

## Request body

- InternalDeliveryHttpHandlerUpdateContactRequest
  - `active` boolean
  - `blacklisted` boolean
  - `custom_avatar_url` string: CustomAvatarURL replaces the picture override. Send "" to CLEAR it, which falls a linked contact back to that person's own profile picture; omit the field to leave it unchanged.
  - `custom_email` string
  - `custom_first_name` string
  - `custom_last_name` string
  - `custom_phone_number` string
  - `custom_wallet_address` string: CustomWalletAddress registers the pay-to wallet on a CUSTOM contact — the act that makes the contact payable, since send destinations derive from the address book. Send "" to CLEAR it, which revokes that permission; omit to leave unchanged. Rejected (400) on a linked contact, whose address is their own account's active wallet.
  - `description` string
  - `name` string

## Response `200`

OK

- InternalDeliveryHttpHandlerContactResponse
  - `data` EnforcerV3InternalDomainContactContact
    - `active` boolean
    - `alerts` EnforcerV3InternalDomainContactContactAlerts
      - `received_unseen` integer
      - `sent_unseen` integer
      - `total` integer
    - `avatar_url` string: AvatarURL is the resolved picture the client should render: the owner's CustomAvatarURL override when set, else the linked person's own profile_image_url. Computed on list/get so the PWA has ONE field to read and never has to implement the precedence itself. Never stored.
    - `blacklisted` boolean
    - `contact_account_id` string
    - `contact_type` string
    - `created_at` string
    - `created_by` string
    - `custom_avatar_url` string: CustomAvatarURL is the OWNER's private picture override for this contact (migration 000057). Meaningful on both contact types: on a linked contact it shadows the linked person's own profile_image_url, on a custom contact it is the only picture there is. nil = no override.
    - `custom_email` string
    - `custom_first_name` string
    - `custom_last_name` string
    - `custom_phone_number` string
    - `custom_wallet_address` string: CustomWalletAddress is a manually-entered pay-to wallet on a custom contact (custom contacts have no account to derive WalletAddress from). Ported from v2; only custom contacts ever set it.
    - `description` string
    - `email` string
    - `favorite_rank` integer: FavoriteRank orders the owner's favorite contacts: nil = not favorited, 1 = first favorite. A user may hold MANY favorites — the rank is a per-owner ordering, not a single slot (unique per owner among non-null ranks, see migration 000056). Favorites float to the top of every list.
    - `first_name` string
    - `id` string
    - `last_name` string
    - `my_account_id` string
    - `name` string
    - `tenant_id` string
    - `updated_at` string
    - `updated_by` string
    - `username` string: FirstName/LastName/Email are computed display fields populated by the contacts usecase on list/get: for linked contacts from the contact's account, for custom contacts mirrored from the custom_* columns. This gives the PWA one uniform name/email shape per row (matching the legacy contacts list) without a second lookup. Never stored. Username is the linked contact's account handle (@username), populated on list/get so the PWA can show @handle instead of falling back to email. Custom contacts have no account, so it stays nil. Never stored.
    - `wallet_address` string: WalletAddress is a computed field populated by the contacts usecase for linked contacts — the embedded wallet of the contact's account. Never stored in the contacts table; loaded from accounts on list/get.
  - `success` boolean

## Other responses

- `400`: Bad Request
- `401`: Unauthorized
- `403`: Forbidden
- `404`: Not Found
- `409`: Conflict

---

[API](https://skmtc.dev/instruxi/apis/enforcer-api.md) · [All operations](https://skmtc.dev/instruxi/apis/enforcer-api/llms.txt) · [OpenAPI document](https://skmtc.dev/instruxi/apis/enforcer-api/revisions/fa82bc1becc0?raw)
