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

# POST /chat

> Generate AI responses with patient context and conversation history

<Note>
  **Recommended:** Use [conversation threads](/conversation-threads) for automatic context management. Include a `threadId` in your request to let the server handle conversation history automatically.
</Note>

## Endpoint

```
POST https://api.mycura.org/api/cura/chat
```

## Request Body

<ParamField body="message" type="string" required>
  The user's question or message to send to the AI
</ParamField>

<ParamField body="threadId" type="string">
  **Recommended:** 5-digit conversation thread ID from [POST /threads](/api-reference/endpoint/create-thread).

  When provided:

  * Server automatically loads last 20 messages as context
  * No need to send `conversationHistory` manually
  * Thread expiration timer resets
  * Returns updated `messageCount` in response

  See the [Conversation Threads guide](/conversation-threads) for details.
</ParamField>

<ParamField body="patientId" type="string">
  UUID of the patient for context retrieval. Only needed if not using a thread or if thread wasn't created with patient info.
</ParamField>

<ParamField body="phone" type="string">
  Patient's phone number for lookup if patientId is not available. Accepts ANY format:

  * `+15551234567` (E.164 format)
  * `15551234567` (11-digit)
  * `5551234567` (10-digit)
  * `(555) 123-4567` (formatted)
  * The system automatically normalizes all formats for lookup
</ParamField>

<ParamField body="patientData" type="object">
  Patient information to override or supplement stored data

  <Expandable title="Patient Data Fields">
    <ParamField body="name" type="string">Patient's full name</ParamField>
    <ParamField body="age" type="number">Patient's age</ParamField>
    <ParamField body="gender" type="string">Patient's gender</ParamField>
    <ParamField body="height" type="string">Patient's height</ParamField>
    <ParamField body="weight" type="string">Patient's weight</ParamField>
    <ParamField body="race" type="string">Patient's race/ethnicity</ParamField>
    <ParamField body="blood_type" type="string">Patient's blood type</ParamField>
    <ParamField body="conditions" type="array">Array of medical conditions</ParamField>
    <ParamField body="allergies" type="array">Array of known allergies</ParamField>
    <ParamField body="medications" type="array">Array of current medications with dosage information</ParamField>
    <ParamField body="last_visit" type="string">Date of last medical visit</ParamField>
    <ParamField body="category_note" type="string">Additional notes or category information</ParamField>
    <ParamField body="phone_number" type="string">Patient's phone number</ParamField>
    <ParamField body="reminders_enabled" type="boolean">Whether reminders are enabled for this patient</ParamField>
  </Expandable>
</ParamField>

<ParamField body="conversationHistory" type="array">
  Array of previous conversation messages for context

  <Expandable title="Conversation History Format">
    Each message should contain:
    <ParamField body="role" type="string">Either "user" or "assistant"</ParamField>
    <ParamField body="content" type="string">The message content</ParamField>
  </Expandable>
</ParamField>

## Response

<ResponseField name="success" type="boolean">
  Indicates if the request was successful
</ResponseField>

<ResponseField name="response" type="string">
  The AI-generated response to the user's message
</ResponseField>

<ResponseField name="threadId" type="string">
  The thread ID (only present when using threads)
</ResponseField>

<ResponseField name="messageCount" type="number">
  Total number of messages in the thread (only present when using threads)
</ResponseField>

<ResponseField name="error" type="string">
  Error message if the request failed (only present when success is false)
</ResponseField>

## Examples

### With Thread (Recommended)

Use a `threadId` for automatic context management across multiple messages.

<CodeGroup>
  ```bash cURL theme={null}
  # First, create a thread (do this once)
  curl -X POST "https://api.mycura.org/api/cura/threads" \
    -H "X-API-Key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{}'

  # Returns: {"threadId": "82451", "initialMessage": "Are you male or female?", ...}

  # Then use the threadId in chat requests
  curl -X POST "https://api.mycura.org/api/cura/chat" \
    -H "Content-Type: application/json" \
    -H "X-API-Key: YOUR_API_KEY" \
    -d '{
      "threadId": "82451",
      "message": "I have been experiencing headaches"
    }'

  # AI remembers automatically on next message!
  curl -X POST "https://api.mycura.org/api/cura/chat" \
    -H "Content-Type: application/json" \
    -H "X-API-Key: YOUR_API_KEY" \
    -d '{
      "threadId": "82451",
      "message": "What could be causing them?"
    }'
  ```

  ```javascript Node.js theme={null}
  // Create thread once
  const threadResp = await fetch('https://api.mycura.org/api/cura/threads', {
    method: 'POST',
    headers: {
      'X-API-Key': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({})
  });

  const { threadId, initialMessage } = await threadResp.json();
  // Display initialMessage if present

  // Use threadId in messages - context is automatic!
  let response = await fetch('https://api.mycura.org/api/cura/chat', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      threadId: threadId,
      message: 'I have been experiencing headaches'
    })
  });

  console.log((await response.json()).response);

  // AI remembers the previous message automatically
  response = await fetch('https://api.mycura.org/api/cura/chat', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      threadId: threadId,
      message: 'What could be causing them?'
    })
  });

  console.log((await response.json()).response);
  ```

  ```python Python theme={null}
  import requests

  # Create thread once
  thread_resp = requests.post(
      'https://api.mycura.org/api/cura/threads',
      headers={'X-API-Key': 'YOUR_API_KEY'},
      json={}
  )

  thread_data = thread_resp.json()
  thread_id = thread_data['threadId']
  # Display initial_message if present

  # Use thread_id in messages - context is automatic!
  response = requests.post(
      'https://api.mycura.org/api/cura/chat',
      headers={
          'Content-Type': 'application/json',
          'X-API-Key': 'YOUR_API_KEY'
      },
      json={
          'threadId': thread_id,
          'message': 'I have been experiencing headaches'
      }
  )

  print(response.json()['response'])

  # AI remembers the previous message automatically
  response = requests.post(
      'https://api.mycura.org/api/cura/chat',
      headers={
          'Content-Type': 'application/json',
          'X-API-Key': 'YOUR_API_KEY'
      },
      json={
          'threadId': thread_id,
          'message': 'What could be causing them?'
      }
  )

  print(response.json()['response'])
  ```
</CodeGroup>

**Response:**

```json theme={null}
{
  "success": true,
  "response": "Headaches can be caused by various factors including...",
  "threadId": "82451",
  "messageCount": 4
}
```

### Basic Request (Without Thread)

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.mycura.org/api/cura/chat" \
    -H "Content-Type: application/json" \
    -H "X-API-Key: YOUR_API_KEY" \
    -d '{
      "message": "What side effects should I expect from Lisinopril?"
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://api.mycura.org/api/cura/chat', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      message: 'What side effects should I expect from Lisinopril?'
    })
  });

  const data = await response.json();
  console.log(data.response);
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.mycura.org/api/cura/chat',
      headers={
          'Content-Type': 'application/json',
          'X-API-Key': 'YOUR_API_KEY'
      },
      json={
          'message': 'What side effects should I expect from Lisinopril?'
      }
  )

  data = response.json()
  print(data['response'])
  ```
</CodeGroup>

### Request with Patient Context

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.mycura.org/api/cura/chat" \
    -H "Content-Type: application/json" \
    -H "X-API-Key: YOUR_API_KEY" \
    -d '{
      "message": "What side effects should I watch for?",
      "patientId": "patient-uuid-123",
      "conversationHistory": [
        {"role": "user", "content": "I was prescribed Lisinopril"},
        {"role": "assistant", "content": "Lisinopril is an ACE inhibitor used to treat high blood pressure..."}
      ]
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://api.mycura.org/api/cura/chat', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      message: 'What side effects should I watch for?',
      patientId: 'patient-uuid-123',
      conversationHistory: [
        { role: 'user', content: 'I was prescribed Lisinopril' },
        { role: 'assistant', content: 'Lisinopril is an ACE inhibitor used to treat high blood pressure...' }
      ]
    })
  });

  const data = await response.json();
  console.log(data.response);
  ```
</CodeGroup>

### Request with Patient Data Override

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.mycura.org/api/cura/chat" \
    -H "Content-Type: application/json" \
    -H "X-API-Key: YOUR_API_KEY" \
    -d '{
      "message": "Are there any drug interactions I should know about?",
      "patientId": "patient-uuid-123",
      "patientData": {
        "medications": [
          {
            "name": "Lisinopril",
            "dosage": "10mg",
            "condition": "Hypertension"
          },
          {
            "name": "Metformin",
            "dosage": "500mg",
            "condition": "Type 2 Diabetes"
          }
        ],
        "allergies": ["Penicillin"]
      }
    }'
  ```
</CodeGroup>

### Phone Number Lookup

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.mycura.org/api/cura/chat" \
    -H "Content-Type: application/json" \
    -H "X-API-Key: YOUR_API_KEY" \
    -d '{
      "message": "What should I know about my prescription?",
      "phone": "+15551234567"
    }'
  ```
</CodeGroup>

## Response Examples

### Success Response

```json theme={null}
{
  "success": true,
  "response": "Common side effects of Lisinopril include a dry cough (in about 10-15% of patients), dizziness, headache, and fatigue. More serious but rare side effects can include swelling of the face, lips, or throat (angioedema), which requires immediate medical attention. Given your medical history, monitor for any persistent cough or dizziness, especially when standing up quickly."
}
```

### Error Response

```json theme={null}
{
  "success": false,
  "error": "Patient not found with the provided ID"
}
```

## Frontend Integration Example

Complete example showing proper thread creation and initial message handling:

```javascript theme={null}
// 1. Create thread on page load or chat initialization
async function initializeChat() {
  const response = await fetch('https://api.mycura.org/api/cura/threads', {
    method: 'POST',
    headers: {
      'X-API-Key': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({})  // Empty body for general conversation
  });
  
  const data = await response.json();
  const threadId = data.threadId;
  
  // Display initial message if present
  if (data.initialMessage) {
    displayMessage('ai', data.initialMessage);
  }
  
  return threadId;
}

// 2. Send user messages
async function sendMessage(threadId, userMessage) {
  // Display user message immediately
  displayMessage('user', userMessage);
  
  const response = await fetch('https://api.mycura.org/api/cura/chat', {
    method: 'POST',
    headers: {
      'X-API-Key': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      threadId: threadId,
      message: userMessage
    })
  });
  
  const data = await response.json();
  if (data.success) {
    displayMessage('ai', data.response);
  } else {
    console.error('Chat error:', data.error);
  }
}

// 3. Helper function to display messages in UI
function displayMessage(sender, text) {
  const messageDiv = document.createElement('div');
  messageDiv.className = `message ${sender}`;
  messageDiv.textContent = text;
  document.getElementById('chat-container').appendChild(messageDiv);
}

// Usage example
let currentThreadId;

// Initialize when chat opens
document.getElementById('start-chat').addEventListener('click', async () => {
  currentThreadId = await initializeChat();
});

// Handle user input
document.getElementById('send-button').addEventListener('click', async () => {
  const input = document.getElementById('user-input');
  const message = input.value.trim();
  
  if (message && currentThreadId) {
    await sendMessage(currentThreadId, message);
    input.value = '';
  }
});
```

## Best Practices

<AccordionGroup>
  <Accordion icon="user-check" title="Use Patient IDs">
    Always provide a `patientId` when available for:

    * More accurate, personalized responses
    * Complete audit trails for compliance
    * Automatic context from stored patient data
  </Accordion>

  <Accordion icon="clock" title="Conversation History">
    Include the last 5-10 conversation turns for context:

    * Maintains conversation continuity
    * Provides better contextual understanding
    * Avoids repetitive responses
  </Accordion>

  <Accordion icon="phone" title="Phone Format Flexibility">
    Phone numbers can be provided in ANY format - the system will automatically normalize them:

    * `+15551234567`, `15551234567`, `5551234567`
    * `(555) 123-4567`, `555-123-4567`, `555.123.4567`
    * All formats work equally well for patient lookup
  </Accordion>

  <Accordion icon="database" title="Patient Data Override">
    Use `patientData` to:

    * Provide temporary context without updating records
    * Override specific fields for the current conversation
    * Include recent changes not yet stored in the system
  </Accordion>

  <Accordion icon="message" title="Display Initial Messages">
    When creating a thread, the API may return an `initialMessage` in the response. Always display this to the user, as it contains important context-gathering questions (like demographics) that improve conversation quality.

    Example flow:

    1. Create thread: POST /threads → receives initialMessage
    2. Display initialMessage in UI immediately
    3. User responds to the question
    4. Continue conversation with subsequent messages
  </Accordion>

  <Accordion icon="triangle-exclamation" title="Port Conflicts (macOS Development)">
    If you're developing on macOS and getting HTTP 403 errors when running locally on port 5000, this is likely due to macOS AirPlay Receiver using that port.

    **Solution:** Use a different port (e.g., 8080, 3000, 8000) for your local development server.
  </Accordion>
</AccordionGroup>

## Error Codes

| Status Code | Error Message                    | Description                                |
| ----------- | -------------------------------- | ------------------------------------------ |
| 400         | "message is required"            | The message field is missing or empty      |
| 401         | "Unauthorized - Invalid API key" | The provided API key is invalid or missing |
| 500         | "Failed to process chat request" | An unexpected error occurred               |

<Note>
  **Phone Lookup**: If a phone number is provided but no patient is found, the request will still proceed without patient context rather than returning an error.
</Note>
