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

# Submit Feedback via API

> Programmatically send user feedback to Squad from your applications, services, or custom integrations

## Overview

The Squad API allows you to programmatically submit user feedback, support tickets, survey responses, or any text-based insights directly into your Squad workspace. This enables you to capture feedback from custom sources and integrate Squad's analysis into your existing workflows.

<Info>
  **Use cases**: Custom feedback forms, internal tools, mobile apps, chatbots, support systems, or any application where users provide feedback.
</Info>

## Benefits

**Real-time feedback ingestion:** Push feedback to Squad as it happens, ensuring your product insights are always up-to-date.

**Source attribution:** Tag feedback with custom source identifiers to track which channels generate the most valuable insights.

**Automated discovery:** Squad's AI automatically analyzes submitted feedback, clusters themes, and surfaces actionable opportunities without manual review.

## Quick start

The fastest way to get started is by pasting this prompt into claude code or your favorite AI coding assistant to automatically generate a plan for integrating feedback capturing into your application:

```bash prompt theme={null}
I want you to visit and understand https://docs.meetsquad.ai/guides/squad-api

I then want you to understand where we might integrate this feedback capturing to this application. I want to capture high quality user feedback. Follow the best practices as outlined in the documentation. If you need to create a feedback form respect the components and patterns in the codebase.

Create a plan and confirm it with me before you implement anything.
```

## Two approaches

<CardGroup cols={2}>
  <Card title="Node.js Client Library" icon="npm" href="#using-the-npm-package">
    Pre-built TypeScript/Node.js package with type safety and error handling
  </Card>

  <Card title="Direct API Integration" icon="globe" href="#using-the-rest-api">
    Build your own client in any language using our REST API
  </Card>
</CardGroup>

## Prerequisites

<Steps>
  <Step title="Get your API key">
    1. Navigate to **Workspace dropdown → Settings** in Squad
    2. Find the **API Access** section
    3. Click **Generate API Key** or copy your existing key

    <Info>
      API keys are workspace-scoped. Each workspace has its own unique key.
    </Info>
  </Step>

  <Step title="Choose your integration approach">
    * **Node.js/TypeScript projects**: Use the npm package for fastest setup
    * **Other languages**: Use the REST API directly
  </Step>
</Steps>

***

## Using the npm package

The official `@squadai/feedback-client` package provides a simple, type-safe way to submit feedback from Node.js applications.

### Installation

<CodeGroup>
  ```bash npm theme={null}
  npm install @squadai/feedback-client
  ```

  ```bash yarn theme={null}
  yarn add @squadai/feedback-client
  ```

  ```bash pnpm theme={null}
  pnpm add @squadai/feedback-client
  ```
</CodeGroup>

### Quick start

<Steps>
  <Step title="Set your API key">
    Add your Squad API key to your environment variables:

    ```bash .env theme={null}
    SQUAD_API_KEY=your-api-key-here
    ```

    <Note>
      The package automatically reads from `process.env.SQUAD_API_KEY` for security. Never hardcode API keys in your source code.
    </Note>
  </Step>

  <Step title="Submit feedback">
    ```typescript theme={null}
    import { submitFeedback } from "@squadai/feedback-client";

    const result = await submitFeedback("The checkout process is too complicated", { source: "CHECKOUT_COMPLETE_FEEDBACK_PAGE" });

    if (result.success) {
      console.log("✓ Feedback submitted to workspace:", result.data.data.workspaceId);
    } else {
      console.error("✗ Error:", result.error.message);
    }
    ```

    That's it! Squad will automatically analyze the feedback and integrate it into your insights.
  </Step>
</Steps>

### Common patterns

<Tabs>
  <Tab title="Web application">
    ```typescript theme={null}
    import express from "express";
    import { submitFeedback } from "@squadai/feedback-client";

    const app = express();
    app.use(express.json());

    app.post("/api/feedback", async (req, res) => {
      const { feedback, userEmail } = req.body;

      if (!feedback) {
        return res.status(400).json({ error: "Feedback is required" });
      }

      // Optionally include user context in the feedback
      const feedbackText = `${feedback}\n\nSubmitted by: ${userEmail}`;

      const result = await submitFeedback(feedbackText, {
        source: "WEB_FORM"
      });

      if (result.success) {
        res.json({ message: "Thank you for your feedback!" });
      } else {
        res.status(500).json({ error: "Failed to submit feedback" });
      }
    });

    app.listen(3000);
    ```
  </Tab>

  <Tab title="Chat integration">
    ```typescript theme={null}
    import { submitFeedback } from "@squadai/feedback-client";

    // When user provides feedback in chat
    async function handleFeedbackCommand(message: string, userId: string) {
      const feedbackWithContext = `${message}\n\nUser ID: ${userId}`;

      const result = await submitFeedback(feedbackWithContext, {
        source: "SLACK_BOT"
      });

      return result.success
        ? "Thanks! Your feedback has been recorded."
        : "Sorry, failed to record feedback. Please try again.";
    }
    ```
  </Tab>

  <Tab title="Mobile backend">
    ```typescript theme={null}
    import { submitFeedback } from "@squadai/feedback-client";

    // API endpoint called from mobile app
    export async function submitAppFeedback(
      feedback: string,
      metadata: { appVersion: string; platform: string }
    ) {
      const enrichedFeedback = `${feedback}\n\nApp: ${metadata.appVersion} (${metadata.platform})`;

      const result = await submitFeedback(enrichedFeedback, {
        source: "MOBILE_APP"
      });

      return {
        success: result.success,
        error: result.success ? null : result.error.message
      };
    }
    ```
  </Tab>
</Tabs>

### Source naming

The `source` parameter helps you track which channels generate feedback. It must follow strict formatting:

<CodeGroup>
  ```typescript Valid Sources theme={null}
  // ✅ Uppercase letters and underscores only
  const validSources = [
    "WEB_FORM",
    "MOBILE_APP",
    "SLACK_BOT",
    "SUPPORT_TICKET",
    "USER_INTERVIEW",
    "API_INTEGRATION",
    "SURVEY_IMPORT"
  ];

  await submitFeedback("Great feature!", {
    source: "WEB_FORM" // ✅ Correct
  });
  ```

  ```typescript Invalid Sources theme={null}
  // ❌ These will throw an error
  await submitFeedback("Great feature!", {
    source: "web-form" // ❌ Lowercase and hyphens
  });

  await submitFeedback("Great feature!", {
    source: "WebForm" // ❌ Mixed case
  });

  await submitFeedback("Great feature!", {
    source: "WEB FORM" // ❌ Spaces not allowed
  });

  await submitFeedback("Great feature!", {
    source: "WEB_FORM_123" // ❌ Numbers not allowed
  });
  ```
</CodeGroup>

<Tip>
  **Pro tip**: Use descriptive source names that match your analytics. For example, `MOBILE_APP` vs `WEB_APP` lets you compare feedback across platforms in Squad Insights.
</Tip>

***

## Using the REST API

For non-Node.js projects or custom implementations, use Squad's REST API directly. You can access the complete openAPI spec here: [OpenAPI Spec](https://api.meetsquad.ai/openapi.json)

### Authentication

All API requests require an API key in the Authorization header:

```bash theme={null}
Authorization: your-api-key-here
```

### Endpoints

<Tabs>
  <Tab title="Basic submission">
    **POST** `/v1/data-ingress`

    Submit feedback without source attribution.

    ```bash cURL theme={null}
    curl -X POST https://api.meetsquad.ai/v1/data-ingress \
      -H "Authorization: your-api-key-here" \
      -H "Content-Type: text/plain" \
      -d "The mobile app crashes when I try to upload photos"
    ```

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

    api_key = "your-api-key-here"
    feedback = "The mobile app crashes when I try to upload photos"

    response = requests.post(
        "https://api.meetsquad.ai/v1/data-ingress",
        headers={
            "Authorization": api_key,
            "Content-Type": "text/plain"
        },
        data=feedback
    )

    if response.status_code == 201:
        data = response.json()
        print(f"✓ Feedback submitted to workspace: {data['data']['workspaceId']}")
    else:
        print(f"✗ Error: {response.status_code}")
    ```

    ```javascript JavaScript (fetch) theme={null}
    const apiKey = "your-api-key-here";
    const feedback = "The mobile app crashes when I try to upload photos";

    const response = await fetch("https://api.meetsquad.ai/v1/data-ingress", {
      method: "POST",
      headers: {
        "Authorization": apiKey,
        "Content-Type": "text/plain"
      },
      body: feedback
    });

    if (response.ok) {
      const data = await response.json();
      console.log(`✓ Feedback submitted to workspace: ${data.data.workspaceId}`);
    } else {
      console.error(`✗ Error: ${response.status}`);
    }
    ```

    ```go Go theme={null}
    package main

    import (
        "bytes"
        "fmt"
        "io"
        "net/http"
    )

    func submitFeedback(apiKey, feedback string) error {
        url := "https://api.meetsquad.ai/v1/data-ingress"

        req, err := http.NewRequest("POST", url, bytes.NewBufferString(feedback))
        if err != nil {
            return err
        }

        req.Header.Set("Authorization", apiKey)
        req.Header.Set("Content-Type", "text/plain")

        client := &http.Client{}
        resp, err := client.Do(req)
        if err != nil {
            return err
        }
        defer resp.Body.Close()

        if resp.StatusCode == 201 {
            fmt.Println("✓ Feedback submitted successfully")
        } else {
            body, _ := io.ReadAll(resp.Body)
            fmt.Printf("✗ Error: %d - %s\n", resp.StatusCode, string(body))
        }

        return nil
    }
    ```
  </Tab>

  <Tab title="With source">
    **POST** `/v1/data-ingress/{feedbackSource}`

    Submit feedback with source attribution for better tracking.

    ```bash cURL theme={null}
    curl -X POST https://api.meetsquad.ai/v1/data-ingress/MOBILE_APP \
      -H "Authorization: your-api-key-here" \
      -H "Content-Type: text/plain" \
      -d "Love the new dark mode feature!"
    ```

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

    api_key = "your-api-key-here"
    feedback = "Love the new dark mode feature!"
    source = "MOBILE_APP"  # Must be UPPERCASE_WITH_UNDERSCORES

    response = requests.post(
        f"https://api.meetsquad.ai/v1/data-ingress/{source}",
        headers={
            "Authorization": api_key,
            "Content-Type": "text/plain"
        },
        data=feedback
    )

    if response.status_code == 201:
        print("✓ Feedback submitted with source:", source)
    else:
        print(f"✗ Error: {response.status_code}")
    ```

    ```ruby Ruby theme={null}
    require 'net/http'
    require 'uri'

    api_key = "your-api-key-here"
    feedback = "Love the new dark mode feature!"
    source = "MOBILE_APP"

    uri = URI("https://api.meetsquad.ai/v1/data-ingress/#{source}")

    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true

    request = Net::HTTP::Post.new(uri)
    request["Authorization"] = api_key
    request["Content-Type"] = "text/plain"
    request.body = feedback

    response = http.request(request)

    if response.code == "201"
      puts "✓ Feedback submitted with source: #{source}"
    else
      puts "✗ Error: #{response.code}"
    end
    ```

    ```php PHP theme={null}
    <?php
    $apiKey = "your-api-key-here";
    $feedback = "Love the new dark mode feature!";
    $source = "MOBILE_APP";

    $ch = curl_init("https://api.meetsquad.ai/v1/data-ingress/{$source}");
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $feedback);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        "Authorization: {$apiKey}",
        "Content-Type: text/plain"
    ]);

    $response = curl_exec($ch);
    $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($statusCode === 201) {
        echo "✓ Feedback submitted with source: {$source}\n";
    } else {
        echo "✗ Error: {$statusCode}\n";
    }
    ?>
    ```
  </Tab>
</Tabs>

### Response format

**Success (201 Created):**

```json theme={null}
{
  "data": {
    "id": "insight_abc123",
    "workspaceId": "ws_xyz789",
    "content": "The mobile app crashes when I try to upload photos",
    "source": "MOBILE_APP",
    "createdAt": "2024-01-15T10:30:00Z"
  }
}
```

**Error responses:**

| Status | Meaning      | Common causes                       |
| ------ | ------------ | ----------------------------------- |
| 400    | Bad Request  | Empty feedback, invalid format      |
| 401    | Unauthorized | Missing or invalid API key          |
| 500    | Server Error | Temporary issue, retry with backoff |

### Check authentication

Use the `whoami` endpoint to verify your API key:

```bash cURL theme={null}
curl https://api.meetsquad.ai/v1/whoami \
  -H "Authorization: your-api-key-here"
```

```json Response theme={null}
{
  "organizationId": "org_123",
  "organizationName": "Acme Corp",
  "workspaceId": "ws_456",
  "workspaceName": "Product Feedback"
}
```

***

## Best practices

<CardGroup cols={2}>
  <Card title="Add context" icon="message-lines">
    Include metadata like user ID, platform, or app version in the feedback text
  </Card>

  <Card title="Use sources consistently" icon="tags">
    Standardize source names across your org (e.g., always use `MOBILE_APP` not variations)
  </Card>

  <Card title="Handle errors gracefully" icon="triangle-exclamation">
    Implement retry logic with exponential backoff for transient failures
  </Card>
</CardGroup>

### Formatting feedback

**Structure feedback for better analysis:**

<CodeGroup>
  ```text Good Feedback theme={null}
  "The checkout process is too slow. It takes 5-6 clicks to complete a purchase and I have to re-enter my payment info every time.

  User: john@example.com
  Platform: iOS
  App Version: 2.3.1"

  Why this works:
  ✓ Specific problem described
  ✓ Measurable details (5-6 clicks)
  ✓ Context included (payment re-entry)
  ✓ Metadata for segmentation
  ```

  ```text Poor Feedback theme={null}
  "App is bad"

  Why this doesn't work:
  ✗ Too vague - no actionable insights
  ✗ No context or details
  ✗ Can't be clustered with similar issues
  ✗ Missing metadata
  ```
</CodeGroup>

***

## Troubleshooting

**Feedback not appearing in Squad**

* Verify API key is correct and workspace-scoped
* Check that feedback text is non-empty
* Ensure API response was 201 (not 400 or 500)
* Give Squad 30-60 seconds to process and cluster new insights

**401 Unauthorized errors**

* Confirm API key is set in environment variables (for npm package)
* Verify API key hasn't been regenerated or revoked
* Check you're using the correct workspace's key
* Test with the `/whoami` endpoint to validate authentication

**Source parameter errors**

* Source must be UPPERCASE\_WITH\_UNDERSCORES only
* No numbers, hyphens, or spaces allowed
* Defaults to `UNKNOWN` if not specified

**Timeout issues**

* Default timeout is 10 seconds
* Increase timeout for slower connections: `{ timeout: 30000 }`
* Check your network connectivity
* Try with a smaller batch size

***

## What's next?

<CardGroup cols={2}>
  <Card title="View your insights" icon="bolt" href="/features/insights">
    See how Squad analyzes and clusters your API-submitted feedback
  </Card>

  <Card title="Integrations" icon="plug" href="/integrations">
    Connect additional data sources for richer insights
  </Card>

  <Card title="Chat with data" icon="messages" href="/features/chat">
    Ask Squad questions about your API-submitted feedback
  </Card>

  <Card title="Build strategy" icon="sitemap" href="/features/strategy">
    Turn feedback into opportunities and solutions
  </Card>
</CardGroup>

<Info>
  **Need help?** Contact [support@meetsquad.ai](mailto:support@meetsquad.ai) or check our [API documentation](https://api.meetsquad.ai/docs) for more details.
</Info>
