Layers
Partner APIAPI referenceProjects

POST /v1/projects/:projectId/ingest/website

Scrape a marketing URL and patch the project's brand context.

View as Markdown
POST/v1/projects/:projectId/ingest/website
Phase 1stableidempotent
Auth
Bearer
Scope
ingest:write

Kicks off a job that fetches a URL, extracts brand signal (name, description, tagline, audience, voice, keywords, logo), and writes the merged result back onto the project's brandContext. Call it when you have a marketing site for the user's app but no GitHub repo — or when the site is richer than the repo README.

Returns 202 with a job envelope. Poll GET /v1/jobs/:jobId for completion; the final brandContext lands on the project itself. Most sites finish in under 10 seconds.

Path
  • projectId
    stringrequired
    Project ID.
Headers
  • Idempotency-Key
    string (UUID)optional
    Replays within 24h.
Body
  • url
    stringrequired
    Absolute http(s) URL. Must resolve and return HTML.
  • followLinks
    booleanoptionaldefault: false
    If true, the crawler follows in-domain links to enrich the extraction.
  • maxPages
    integeroptionaldefault: 1
    Cap on pages fetched when `followLinks` is true. 1–25.

Example request

curl -X POST https://api.layers.com/v1/projects/9cb958b5-11b5-4e30-8675-5d075d52da7c/ingest/website \
  -H "Authorization: Bearer lp_live_01HX9Y6K7EJ4T2_4QZpN..." \
  -H "Idempotency-Key: a81c6244-4b2f-4d0a-8b5c-9f6de11aaf22" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://acmecoffee.com" }'
const job = await layers.projects.ingestWebsite(
  "9cb958b5-11b5-4e30-8675-5d075d52da7c",
  { url: "https://acmecoffee.com" },
  { idempotencyKey: crypto.randomUUID() }
);
// Returns immediately with `job.jobId`; poll layers.jobs.get(job.jobId).
job = layers.projects.ingest_website(
    project_id="9cb958b5-11b5-4e30-8675-5d075d52da7c",
    url="https://acmecoffee.com",
    idempotency_key=str(uuid.uuid4()),
)
# Poll layers.jobs.get(job.job_id) for completion.

Response

202Accepted — queued
{
  "jobId": "job_01JS5V8KX5JFK1YQ4G2YZQ4XEP",
  "kind": "project_ingest_website",
  "status": "running",
  "stage": "fetching",
  "projectId": "9cb958b5-11b5-4e30-8675-5d075d52da7c",
  "url": "https://acmecoffee.com",
  "locationUrl": "/v1/jobs/job_01JS5V8KX5JFK1YQ4G2YZQ4XEP",
  "startedAt": "2026-04-18T19:25:42.187Z"
}

Poll the URL in locationUrl (which mirrors GET /v1/jobs/:jobId) until status is completed or failed. On success, the resulting brandContext is patched onto the project — re-fetch the project to read it.

Errors

StatusCodeWhen
422VALIDATIONMissing or malformed url.
401UNAUTHENTICATEDMissing or invalid key.
403FORBIDDEN_SCOPEKey lacks ingest:write.
404NOT_FOUNDProject does not exist.
429RATE_LIMITEDWrite budget or external-scrape budget exhausted.

See also

On this page