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

# Agent ingest

> Agent-friendly guide for sending external images into Pindeck

# Agent ingest

Use this guide when an agent, automation, or external service needs to send images into Pindeck from another system. The common path is:

1. Find a public image URL.
2. Build a stable `externalId` for deduplication.
3. Send the image to `/ingestExternal`.
4. Let Pindeck copy the file into RustFS, create the image record, extract colors, and put moderated sources into review.

## Endpoint

```text theme={null}
POST https://convex-site.serving.cloud/ingestExternal
Authorization: Bearer <INGEST_API_KEY>
Content-Type: application/json
```

## Required fields

| Field      | Description                                                |
| ---------- | ---------------------------------------------------------- |
| `imageUrl` | Public URL that Pindeck can download and copy into RustFS. |
| `userId`   | Pindeck user id that owns the imported image.              |

## Recommended fields

| Field           | Description                                                                                                                        |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `sourceType`    | Use `discord`, `pinterest`, `upload`, or `ai`. Moderated sources such as `discord` and `pinterest` enter review before publishing. |
| `externalId`    | Stable idempotency key, such as `pinterest:<board-id>:<pin-id>` or `discord:<guild-id>:<message-id>:<attachment-id>`.              |
| `sourceUrl`     | Original page, pin, post, or message URL.                                                                                          |
| `title`         | Human-readable title.                                                                                                              |
| `description`   | Short context for search and review.                                                                                               |
| `tags`          | Array of searchable tags.                                                                                                          |
| `category`      | Broad classification, usually `General` when unknown.                                                                              |
| `importBatchId` | Optional Convex import batch id, if the integration has already created one. Omit for simple external automations.                 |
| `sref`          | Style reference id when the import came from an SREF workflow.                                                                     |

## Minimal request

```bash theme={null}
curl -X POST "https://convex-site.serving.cloud/ingestExternal" \
  -H "Authorization: Bearer $INGEST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "USER_ID",
    "imageUrl": "https://example.com/image.jpg",
    "sourceType": "pinterest",
    "externalId": "pinterest:board-123:pin-456",
    "sourceUrl": "https://www.pinterest.com/pin/456",
    "title": "Imported reference",
    "tags": ["pinterest", "reference"]
  }'
```

Successful responses return the created `imageId` and resolved `userId`.

```json theme={null}
{
  "imageId": "k17...",
  "userId": "j57..."
}
```

## JavaScript agent example

```ts theme={null}
type PindeckIngestPayload = {
  userId: string;
  imageUrl: string;
  sourceType?: "discord" | "pinterest" | "upload" | "ai";
  externalId?: string;
  sourceUrl?: string;
  title?: string;
  description?: string;
  tags?: string[];
  category?: string;
  importBatchId?: string;
  sref?: string;
};

export async function sendToPindeck(payload: PindeckIngestPayload) {
  const response = await fetch("https://convex-site.serving.cloud/ingestExternal", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.INGEST_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(payload),
  });

  if (!response.ok) {
    throw new Error(`Pindeck ingest failed: ${response.status} ${await response.text()}`);
  }

  return response.json() as Promise<{ imageId: string; userId: string }>;
}
```

## Moderated sources

Images with `sourceType` set to `discord` or `pinterest` are created as draft/moderated imports. They are available to the review workflow before becoming active in the main library.

For Discord-specific review tooling, use `/discordQueue` to list queued items and `/discordModerate` to approve, reject, or generate variations for a queued image.

For Pinterest, keep `sourceUrl` as the original pin/page URL, but still send a
downloadable `imageUrl`. Pindeck stores its own RustFS copy so Pinterest
references remain usable for boards, decks, color extraction, and AI variation
workflows even if the source URL changes later.

## Integration checklist

* Use `externalId` on every automated import.
* Keep `INGEST_API_KEY` server-side only.
* Omit `importBatchId` unless you have a real Convex import batch id.
* Send `sourceUrl` so reviewers can trace where an image came from.
* Prefer direct image URLs that do not require browser cookies.
* Retry `502` responses with backoff; they can mean the upstream image host or RustFS persistence step failed.
