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

# Fetch User by Foreign ID

> Look up a user by your own system's external user ID

export const SpaceReputationParams = ({variant = "context", field = "path"}) => {
  const isUser = variant === "user";
  return <>
      <ParamField {...{
    [field]: "spaceReputation",
    type: "object"
  }}>
        Opt-in. Adds a <code>spaceReputation</code> number to each returned user,
        scoped to a single space. Requires the <code>reputation</code> bundle.
        The <code>reputation</code> total is always present regardless;{" "}
        <code>spaceReputation</code> is purely additive and only appears when you
        pass this object. <strong>This object is the primary form</strong> — it
        replaces the deprecated flat props below. See the{" "}
        <a href="/v8/data-models/reputation">Reputation data model</a> for the
        full contract.

        <Expandable title="spaceReputation">
          {isUser ? <ParamField name="spaceId" type="string | &quot;none&quot;" required>
              Which bucket to read. A space <strong><code>&lt;uuid&gt;</code></strong> reads that
              space's bucket; <strong><code>"none"</code></strong> reads the
              project-general (space-less) bucket.{" "}
              <strong><code>"context"</code> is rejected (400)</strong> on this
              endpoint — there is no space context to derive. The empty string
              and the legacy <code>general</code> / <code>null</code> aliases are
              also rejected. Missing buckets read as <code>0</code>.
            </ParamField> : <ParamField name="spaceId" type="string | &quot;none&quot; | &quot;context&quot;" required>
              Which bucket to read. One of: a space <strong><code>&lt;uuid&gt;</code></strong>{" "}
              (that space's bucket), <strong><code>"none"</code></strong> (the
              project-general, space-less bucket), or{" "}
              <strong><code>"context"</code></strong> (the space derived from the
              request context — resolved per-row on lists, or the single space on
              member/team/conversation surfaces). The empty string and the legacy{" "}
              <code>general</code> / <code>null</code> aliases are rejected (400).
              Missing buckets read as <code>0</code>.
            </ParamField>}
          <ParamField name="includeDescendants" type="boolean">
            Only honored when <code>spaceId</code> is an explicit space <code>&lt;uuid&gt;</code>.
            When <code>true</code>, <code>spaceReputation</code> is the{" "}
            <strong>subtree sum</strong> — the named space plus all of its
            descendant spaces (the root space's own bucket included). Ignored for{" "}
            <code>"none"</code>; not allowed with <code>"context"</code>.
          </ParamField>
        </Expandable>
      </ParamField>

      {isUser ? <ParamField {...{
    [field]: "spaceReputationId",
    type: "string",
    deprecated: true
  }}>
          <strong>Deprecated</strong> — use the <code>spaceReputation</code>{" "}
          object instead. The flat form of <code>spaceReputation.spaceId</code>.
          Still accepted (the object wins if both are passed); removal is a later
          major version. Accepts a space <code>&lt;uuid&gt;</code> or <code>"none"</code> only —{" "}
          <code>"context"</code> is rejected (400) on this endpoint.
        </ParamField> : <ParamField {...{
    [field]: "spaceReputationId",
    type: "string",
    deprecated: true
  }}>
          <strong>Deprecated</strong> — use the <code>spaceReputation</code>{" "}
          object instead. The flat form of <code>spaceReputation.spaceId</code>.
          Still accepted (the object wins if both are passed); removal is a later
          major version. Accepts a space <code>&lt;uuid&gt;</code>, <code>"none"</code>, or{" "}
          <code>"context"</code>.
        </ParamField>}

      <ParamField {...{
    [field]: "spaceReputationDescendants",
    type: "boolean",
    deprecated: true
  }}>
        <strong>Deprecated</strong> — use{" "}
        <code>spaceReputation.includeDescendants</code> instead. The flat form,
        only honored alongside an explicit <code>spaceReputationId</code> <code>&lt;uuid&gt;</code>.
      </ParamField>
    </>;
};

Finds a user within the project by their `foreignId` — the external identifier you provided when creating or syncing the user. Optionally creates the user if not found (requires service or master token).

<Note>
  If the profile owner has blocked the signed-in caller, this returns `404` — the
  same response as a user who does not exist. The reverse is not true: a user
  *you* have blocked stays visible, so you keep a way to find and unblock them. Requires the `moderation` bundle.
</Note>

## Query Parameters

<ParamField query="foreignId" type="string" required>
  The external identifier from your system.
</ParamField>

<ParamField query="include" type="string">
  Comma-separated list of associations to include. Pass `"files"` to include
  the processed `avatarFile` and `bannerFile` objects.
</ParamField>

<ParamField query="createIfNotFound" type="string">
  Set to `"true"` to create the user if they do not exist. Requires a service
  or master token. Returns `201` on creation, `200` on an existing user.
</ParamField>

<ParamField query="name" type="string">
  Display name to set when creating the user (`createIfNotFound` only).
</ParamField>

<ParamField query="username" type="string">
  Username to assign when creating the user (`createIfNotFound` only).
</ParamField>

<ParamField query="avatar" type="string">
  Avatar URL to set when creating the user (`createIfNotFound` only).
</ParamField>

<ParamField query="bio" type="string">
  Bio text to set when creating the user (`createIfNotFound` only).
</ParamField>

<ParamField query="metadata" type="string">
  JSON-encoded public metadata to set when creating the user
  (`createIfNotFound` only).
</ParamField>

<ParamField query="secureMetadata" type="string">
  JSON-encoded private metadata to set when creating the user
  (`createIfNotFound` only).
</ParamField>

### Space-scoped reputation

This endpoint has no space in context, so the opt-in `spaceReputation` object accepts a `spaceId` of a space **`<uuid>`** or **`none`** only — `context` is rejected (400). It adds a `spaceReputation` field to each returned user, alongside the always-present `reputation` total. Requires the `reputation` bundle. See the [Reputation data model](/v8/data-models/reputation).

<SpaceReputationParams variant="user" field="query" />

## Response

Returns HTTP `200` (found) or `201` (created) with the user object:

<ResponseField name="id" type="string">
  Unique user ID (UUID).
</ResponseField>

<ResponseField name="foreignId" type="string | null">
  The foreign ID you provided.
</ResponseField>

<ResponseField name="projectId" type="string">
  Project this user belongs to.
</ResponseField>

<ResponseField name="name" type="string | null">
  Display name.
</ResponseField>

<ResponseField name="username" type="string | null">
  Unique username within the project.
</ResponseField>

<ResponseField name="avatar" type="string | null">
  Avatar image URL.
</ResponseField>

<ResponseField name="bio" type="string | null">
  Short bio text.
</ResponseField>

<ResponseField name="metadata" type="object | null">
  Public custom key-value data.
</ResponseField>

<ResponseField name="reputation" type="number">
  Reputation score.
</ResponseField>

<ResponseField name="avatarFile" type="object | null">
  Processed avatar image with variants. Only present when `include=files` is
  requested.
</ResponseField>

<ResponseField name="bannerFile" type="object | null">
  Processed banner image with variants. Only present when `include=files` is
  requested.
</ResponseField>

<ResponseField name="createdAt" type="string">
  ISO timestamp of account creation.
</ResponseField>

<Note>
  `createIfNotFound=true` is only permitted with a **service** or **master**
  token. Client tokens receive a 404 if the user does not exist.
</Note>

## Error Responses

<AccordionGroup>
  <Accordion title="User Not Found — 404">
    ```json theme={null}
    {
      "error": "User not found",
      "code": "user/not-found"
    }
    ```
  </Accordion>

  <Accordion title="Invalid Query — 400">
    ```json theme={null}
    {
      "error": "...",
      "code": "user/invalid-query"
    }
    ```
  </Accordion>
</AccordionGroup>

## See Also

* [`useFetchUserByForeignId` hook](/v8/hooks/users/use-fetch-user-by-foreign-id)
* [External auth guide](/v8/sdk/authentication/external)
* [User data model](/v8/data-models/user)


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