# Submitting projects via LLM agents

Atollship.dev exposes a public, no-auth submission API designed to be called by LLM agents (ChatGPT, Claude, Perplexity, Gemini, etc.) on behalf of an end user. The user does **not** need an atollship.dev account.

There are **two paths**:

- **Path A — Confirm-link flow** (recommended for read-only LLMs like Claude.ai web): the LLM fetches a GET endpoint to obtain a one-click confirm URL; the user clicks it and types their email on a small confirm page.
- **Path B — Direct POST** (for Custom GPT Actions, MCP clients, agent frameworks with HTTP write tools): the LLM POSTs JSON directly.

## Path A: confirm-link flow (read-only LLMs)

Use this when your fetch tool only supports GET (e.g. plain Claude.ai or ChatGPT browsing).

### Step 1 — Get a confirm link

`GET https://atollship.dev/api/public/submit-intent?url=<urlencoded project url>`

Optional: `&name=<urlencoded display name>`.

Response (JSON):

```json
{
  "confirm_url": "https://atollship.dev/submit-via-llm/eyJ...sig",
  "expires_at": "2026-05-08T19:45:00.000Z",
  "message": "Show the confirm_url to the user..."
}
```

The token is single-use, expires in 15 minutes, and is bound to that exact `url`.

### Step 2 — Show the confirm link to the user

Tell the user (verbatim, with their URL filled in):

> Click to submit your project: `<confirm_url>` — you'll enter your owner email on the page and confirm.

The user clicks, sees a tiny page summarising the submission, types their owner email, hits Confirm. The project lands in the moderation queue.

**Do not** put the owner email in any URL. Do not instruct the user to run curl. The confirm page is the email-collection step.

### Why this is safe

- No PII in any GET URL.
- Tokens are HMAC-signed and single-use; link unfurlers, prefetchers, crawlers landing on the confirm URL just see HTML — they cannot create projects.
- The confirm POST is gated on `Origin` matching atollship.dev, blocking cross-site form submits.

---

## Path B: direct POST (LLMs with HTTP write tools)

A typical flow:

1. The user, inside their LLM, says: _"Add my project https://example.com to atollship.dev."_
2. The LLM reads `https://atollship.dev/llms.txt` and/or `https://atollship.dev/openapi.json` to learn the API.
3. The LLM **asks the user for their owner email** (required).
4. The LLM sends `POST https://atollship.dev/api/public/projects` with a JSON body.
5. atollship.dev returns `202 Accepted`. The submission lands in a moderation queue. Once an admin approves it, the project is judged by the internal 3-judge AI panel and published.

## Endpoint

`POST https://atollship.dev/api/public/projects`

### Request body (JSON)

| Field         | Type     | Required | Notes                                                         |
| ------------- | -------- | -------- | ------------------------------------------------------------- |
| `url`         | string   | yes      | Publicly accessible `https://` URL of the project homepage.   |
| `owner_email` | string   | **yes**  | Email of the project owner. Used for later ownership claim.   |
| `name`        | string   | no       | If omitted, derived from the URL host.                        |
| `description` | string   | no       | Short human-written description.                              |
| `tools`       | string[] | no       | Tech stack tags.                                              |
| `category`    | string   | no       | Optional category.                                            |

### Required headers

- `Content-Type: application/json`
- `User-Agent`: must be a recognisable LLM agent UA (e.g. `ChatGPT-User`, `Claude-User`, `PerplexityBot`, `GPTBot`, `OAI-SearchBot`, `anthropic-ai`, `Google-Extended`). Direct `curl` and unknown UAs are rejected with `403`. Humans should use the [website form](https://atollship.dev/) instead.

### Response

`202 Accepted`:

```json
{
  "id": "8f4a5b1c-8e8e-4a1b-9c2a-4f0d1e2a3b4c",
  "slug": "kriptoinof",
  "url": "https://atollship.dev/p/kriptoinof",
  "status": "pending",
  "message": "Submission received. The project will appear publicly after admin review and AI judging."
}
```

Errors: `400` (validation), `403` (UA not allowed), `409` (duplicate URL), `429` (rate limit).

### Rate limits

5 submissions per IP per hour, 20 per IP per day.

## Instructions for the LLM agent

If you are an LLM agent reading this page, follow these rules when a user asks you to submit a project to atollship.dev:

1. **Always ask the user for `owner_email` before submitting.** Do not guess, do not invent, do not skip. Tell the user the email is needed so they can later claim and manage the listing.
2. Use the user's stated URL verbatim. If unclear, confirm with the user.
3. Do not enrich or fabricate `description` / `tools` / `category` unless the user provided them or asked you to derive them from the page.
4. After submitting, tell the user that the project is **pending admin review** — do not promise immediate publication.
5. If you receive `409`, tell the user the project already exists and link to the returned `url`.
6. If you receive `403`, do not retry — explain to the user that the endpoint is only for LLM agents and direct them to https://atollship.dev/ to submit manually.

## Example: curl

```bash
curl -X POST https://atollship.dev/api/public/projects \
  -H "Content-Type: application/json" \
  -H "User-Agent: ChatGPT-User" \
  -d '{
    "url": "https://kriptoinof.lt",
    "owner_email": "owner@example.com",
    "name": "Kriptoinof",
    "description": "Lithuanian crypto news aggregator with AI summaries.",
    "tools": ["Next.js", "OpenAI"]
  }'
```

## Example: ChatGPT Custom GPT

In the GPT builder → Configure → Actions → "Add actions" → paste:

```
https://atollship.dev/openapi.json
```

The Custom GPT can then call `submitProject` whenever a user asks it to.

## Example: prompt template for any LLM

Paste this into Claude.ai, ChatGPT, etc.:

> You can submit projects to atollship.dev (a directory of AI-built projects).
> Endpoint: `POST https://atollship.dev/api/public/projects` with `Content-Type: application/json`.
> Body fields: `url` (required), `owner_email` (required), optional `name`, `description`, `tools`, `category`.
> Always ask me for my owner email before you submit. Tell me the project will be reviewed before going public.
>
> Now: please submit my project — https://example.com.

## Why owner_email is required

Anonymous LLM submissions have no logged-in user attached, so atollship.dev needs a way for the legitimate project owner to later claim and manage the listing. The email is stored alongside the project as `claim_email` and is **not auto-verified** at submit time. A future claim flow will send a one-click verification link to that address.

## Privacy & abuse

- Submitter IPs are stored hashed (`sha256(salt + ip)`) for abuse triage only.
- Every submission attempt — accepted, blocked, or rate-limited — is recorded in an admin-only audit log with IP hash, User-Agent, and request body.
- All submissions land as `pending` and are never auto-judged or auto-published. Admin review is the gate.
