FruxonDocs
Agent NetworkParticipants

Partial update

Applies a partial update: only the non-null fields of the request are written, so callers can patch a single property without resending the whole resource. Supplying `Channels` replaces the channel list wholesale. `Kind` cannot be changed here. Agent bindings are managed through the nested `bindings` sub-resource, not this endpoint.

PATCH
/v1/tenants/{tenant}/participants/{participant}
AuthorizationBearer <token>

JWT Authorization header using the Bearer scheme. Enter 'Bearer' [space] and then your token.

In: header

Path Parameters

participant*string

The participant identifier.

Formatuuid
tenant*string

The tenant identifier

The patch payload — null fields are left unchanged.

displayName?string|null
Lengthlength <= 150
email?string|null

Contact email. Patch semantics: null leaves it unchanged; an empty string explicitly clears it (normalized to null); any other value replaces it.

Lengthlength <= 4000
relatedAgentId?string|null
audience?string

Trust boundary — EXTERNAL (customer/contact) vs INTERNAL (staff/operator). Null leaves it unchanged (patch semantics), matching the other optional fields here.

Value in"UNSPECIFIED" | "UNKNOWN" | "INTERNAL" | "EXTERNAL"
avatarFileId?string|null

Operator-uploaded avatar. Patch semantics: null leaves the existing value alone; an empty string clears it (e.g. when the operator removes the upload). To match this, the service treats the empty string as "explicit clear" rather than coalescing it.

addresses?|null

When provided, replaces the participant's address list entirely. Pass null to leave unchanged; pass an empty list to clear.

agentIds?|null

When provided, reconciles agent bindings to exactly this set in the same call as the rest of the patch — additions and removals are computed against the current bindings. Pass null to leave bindings unchanged; pass an empty list to unbind every agent.

Closes the partial-commit window the FE used to fall into: when the participant dialog used to write the participant PATCH and then fan-out individual PUT/DELETE /bindings/{agent} calls in parallel, a single failing binding op left the operator with a half-applied state. With this field, both the entity update and the binding reconciliation run inside one service call — the granular per-binding endpoints stay for callers that prefer them.

description?string|null

New advisor description. Null leaves it unchanged; an empty string clears it.

Lengthlength <= 4000
expertise?|null

When provided, replaces the participant's consult expertise (capability names). Null leaves it unchanged; an empty list clears it.

area?string|null

New profile area of work. Null leaves it unchanged; an empty string clears it.

Lengthlength <= 150
bio?string|null

New biography. Null leaves it unchanged; an empty string clears it.

Lengthlength <= 4000
preferredLanguage?string|null

New preferred language for notices sent to this participant (ISO 639-1, e.g. "en", "he"). Null leaves it unchanged; an empty string clears it (falls back to auto-detect from the customer's turns).

Lengthlength <= 16
preferences?|null

When provided, replaces the participant's preference tags. Null leaves it unchanged; an empty list clears it.

accounts?|null

When provided, replaces the participant's external account links. Null leaves it unchanged; an empty list clears it.

environmentId?string|null

Re-file the contact under a different environment (directory grouping). Authoritative only when UpdateParticipantRequest.EnvironmentSpecified is true — a non-null value moves the contact (validated against the tenant's environments), an explicit null unaffiliates it. When false the current affiliation is preserved. A plain Guid? can't express "leave unchanged" vs "clear" on its own, so this mirrors the access-request approve payload (RecordAccessRequestCommand.EnvironmentSpecified).

Formatuuid
environmentSpecified?boolean

True when the client set UpdateParticipantRequest.EnvironmentId deliberately (so an explicit null clears the affiliation). False leaves the current environment untouched — the default for a patch that doesn't touch grouping.

[key: string]?never

Response Body

curl -X PATCH "https://api.fruxon.com/v1/tenants/string/participants/497f6eca-6276-4993-bfeb-53cbbbba6f08" \  -H "Content-Type: application/json" \  -d '{}'
{
  "id": "00000000-0000-0000-0000-000000000000",
  "kind": "PERSON",
  "tier": "CURATED",
  "audience": "UNKNOWN",
  "displayName": "string",
  "email": "string",
  "emailProof": {
    "method": "MINTED",
    "at": 0
  },
  "relatedAgentId": "string",
  "description": "string",
  "expertise": [
    "string"
  ],
  "area": "string",
  "bio": "string",
  "preferredLanguage": "string",
  "environmentId": "00000000-0000-0000-0000-000000000000",
  "displayNameSource": "SYNCED",
  "bioSource": "SYNCED",
  "environmentSource": "SYNCED",
  "preferences": [
    "string"
  ],
  "accounts": [
    {
      "provider": "string",
      "identifier": "string",
      "handle": "string",
      "profileUrl": "string",
      "source": "MANUAL",
      "verifiedAt": 0,
      "proof": {
        "method": "UNSPECIFIED",
        "at": 0
      }
    }
  ],
  "addresses": [
    {
      "provider": "string",
      "address": "string",
      "priority": 0,
      "label": "string",
      "disabled": false,
      "proof": {
        "method": "UNSPECIFIED",
        "at": 0
      }
    }
  ],
  "isDebugOnly": false,
  "agentIds": [
    "string"
  ],
  "disabledAt": 0,
  "mergedIntoId": "00000000-0000-0000-0000-000000000000",
  "enrolled": false,
  "autoEnrolled": false,
  "health": {
    "reachable": false,
    "channels": [
      {
        "address": "string",
        "reason": null,
        "keyStatus": "UNSPECIFIED",
        "keyPrefix": "string",
        "lastMessageAt": null
      }
    ],
    "reason": "INVALID_FORMAT"
  },
  "channelActivations": [
    {
      "agentId": "string",
      "bindingId": "00000000-0000-0000-0000-000000000000",
      "integrationConfigId": "00000000-0000-0000-0000-000000000000",
      "provider": "string",
      "address": "string",
      "webhookUrl": "string",
      "webhookUrlTemplate": "string",
      "webhookKeyPrefix": "string",
      "scope": "PER_BINDING"
    }
  ],
  "avatarFileId": "string",
  "avatarSource": "UPLOADED",
  "avatarSourceConfigId": "00000000-0000-0000-0000-000000000000",
  "avatarSourceAddress": "string",
  "avatarSyncedAt": 0,
  "avatarAutoSync": {
    "synced": false,
    "provider": "string",
    "address": "string"
  },
  "createdAt": 0,
  "modifiedAt": 0
}
{
  "type": "string",
  "title": "string",
  "status": 0,
  "detail": "string",
  "instance": "string",
  "property1": null,
  "property2": null
}
Empty
Empty
{
  "type": "string",
  "title": "string",
  "status": 0,
  "detail": "string",
  "instance": "string",
  "property1": null,
  "property2": null
}

Sends one of a person's identities a verification.

For a mailbox (`email`, the directory email, or a mail channel's address) the six-digit code is mailed to the address alone and the answer is `PUSH` with no link: the person replies to that mail with the code, and the reply goes to the workspace's email channel, named in `replyTo`. For Telegram and WhatsApp the answer is `PULL` with the link the person opens from that account; for Slack, the code they send the app in a direct message; for the console, `CONSOLE` with the link they open signed in. The link works once, for 15 minutes, and only from the identity it names. Refused with 400 without an address, 400 `address_not_on_person` for an identity the person does not carry, 400 `not_sendable` for an account the person proves by connecting it (GitHub, Jira, GitLab, Linear), 400 `no_reply_mailbox` for a mailbox when the workspace has no email channel to reply to, 409 `identity_held` with the merge suggestion's id (`mergeSuggestionId` beside `message` and `code`) when someone else in the workspace holds it, and 429 `too_many_links` while the person already has three links open (`Retry-After` says when the first expires).

Evaluates the participant placeholder vocabulary against this participant.

The participant-side mirror of pinned `{{sender.*}}` / `{{venue.*}}` tool parameters: every placeholder in the closed vocabulary (scalar profile fields plus `account.<provider>` / `address.<provider>` selectors for the union of the participant's own providers and the tenant's connected channels) evaluated through the same resolver a real tool call uses. Each row carries either the value that would be injected or the verbatim fail-closed error the tool call would die with — so "why did a pinned tool fail for this person" is answered from the Directory instead of a trace dig. Groups evaluate under the `venue.` root; people and AI agents under `sender.`. Returns 404 when the participant does not exist.