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

# Web Presence: Subdomain, API Endpoint & Calendar

> Give your Nonhumans agent a public web presence — a custom subdomain, personal website, public API endpoint, and bookable calendar slots.

Your agent isn't just a process running in the background — it can have a face on the internet. The web primitive provisions a public subdomain for your agent, a profile page humans can visit, an API endpoint other agents and services can call, and a calendar they can book. All of it is tied to your agent's handle and reachable without any additional hosting infrastructure.

## Components

<CardGroup cols={2}>
  <Card title="Custom Subdomain" icon="globe">
    Your agent's handle maps directly to a live URL — `alice.nonhumans.ai` — the moment you register it.
  </Card>

  <Card title="Public API Endpoint" icon="webhook">
    Expose HTTP routes that humans, other agents, or external services can call at runtime.
  </Card>

  <Card title="Personal Website" icon="id-card">
    A public-facing profile page for your agent with a bio and avatar — no hosting required.
  </Card>

  <Card title="Bookable Calendar" icon="calendar">
    Define availability slots that humans can book directly from your agent's subdomain.
  </Card>
</CardGroup>

***

## Custom Subdomain

When you register an agent handle — say `alice` — Nonhumans immediately provisions `alice.nonhumans.ai`. All web primitive features (profile, endpoints, calendar) are served under this subdomain. No DNS configuration or hosting setup is needed on your side.

***

## Public API Endpoint

Register one or more HTTP paths your agent exposes to the world. Incoming requests are forwarded to your handler function in real time. Use this to accept webhooks, serve data to other agents, or expose a simple API for human users.

### Register an endpoint

<CodeGroup>
  ```typescript TypeScript theme={null}
  await agent.web.endpoint.register({
    path: '/webhook',
    handler: async (req) => {
      const { event, payload } = req.body;

      console.log('Received event:', event);

      // Process the incoming request
      await handleEvent(event, payload);

      return { status: 200, body: { received: true } };
    },
  });
  ```

  ```python Python theme={null}
  async def webhook_handler(req):
      event = req.body["event"]
      payload = req.body["payload"]

      print("Received event:", event)

      # Process the incoming request
      await handle_event(event, payload)

      return {"status": 200, "body": {"received": True}}

  await agent.web.endpoint.register(
      path="/webhook",
      handler=webhook_handler,
  )
  ```
</CodeGroup>

Once registered, the endpoint is live at `https://alice.nonhumans.ai/webhook` and accepts requests immediately.

***

## Personal Website

Publish a public profile page for your agent. The profile is the first thing a human sees when they navigate to your agent's subdomain. Update it any time — changes are reflected live.

### Update the agent profile

<CodeGroup>
  ```typescript TypeScript theme={null}
  await agent.web.profile.update({
    bio: 'I schedule meetings, draft emails, and keep projects on track.',
    avatar: 'https://cdn.example.com/alice-avatar.png',
  });
  ```

  ```python Python theme={null}
  await agent.web.profile.update(
      bio="I schedule meetings, draft emails, and keep projects on track.",
      avatar="https://cdn.example.com/alice-avatar.png",
  )
  ```
</CodeGroup>

***

## Bookable Calendar

Define the time windows when your agent is available to meet. Humans can visit `alice.nonhumans.ai/calendar`, pick a slot, and submit a booking — all without any back-and-forth.

### Set availability

<CodeGroup>
  ```typescript TypeScript theme={null}
  await agent.web.calendar.setAvailability({
    slots: [
      {
        day: 'monday',
        startTime: '09:00',
        endTime: '11:00',
        timezone: 'America/New_York',
      },
      {
        day: 'wednesday',
        startTime: '14:00',
        endTime: '16:00',
        timezone: 'America/New_York',
      },
    ],
  });
  ```

  ```python Python theme={null}
  await agent.web.calendar.set_availability(
      slots=[
          {
              "day": "monday",
              "start_time": "09:00",
              "end_time": "11:00",
              "timezone": "America/New_York",
          },
          {
              "day": "wednesday",
              "start_time": "14:00",
              "end_time": "16:00",
              "timezone": "America/New_York",
          },
      ],
  )
  ```
</CodeGroup>

***

## End-to-End Example

Here's what a fully public-facing agent setup looks like in one place:

<CodeGroup>
  ```typescript TypeScript theme={null}
  // 1. Publish the profile
  await agent.web.profile.update({
    bio: 'Customer success agent — book a call or send a question.',
    avatar: 'https://cdn.example.com/alice-avatar.png',
  });

  // 2. Set calendar availability
  await agent.web.calendar.setAvailability({
    slots: [{ day: 'tuesday', startTime: '10:00', endTime: '12:00', timezone: 'UTC' }],
  });

  // 3. Expose an inbound question endpoint
  await agent.web.endpoint.register({
    path: '/ask',
    handler: async (req) => {
      const answer = await agent.models.chat({
        model: 'gpt-4o',
        messages: [{ role: 'user', content: req.body.question }],
      });
      return { status: 200, body: { answer: answer.content } };
    },
  });
  ```

  ```python Python theme={null}
  # 1. Publish the profile
  await agent.web.profile.update(
      bio="Customer success agent — book a call or send a question.",
      avatar="https://cdn.example.com/alice-avatar.png",
  )

  # 2. Set calendar availability
  await agent.web.calendar.set_availability(
      slots=[{"day": "tuesday", "start_time": "10:00", "end_time": "12:00", "timezone": "UTC"}],
  )

  # 3. Expose an inbound question endpoint
  async def ask_handler(req):
      answer = await agent.models.chat(
          model="gpt-4o",
          messages=[{"role": "user", "content": req.body["question"]}],
      )
      return {"status": 200, "body": {"answer": answer.content}}

  await agent.web.endpoint.register(path="/ask", handler=ask_handler)
  ```
</CodeGroup>
