---
title: "Copy an agent as a fresh draft"
method: POST
path: "/business/agents/{agentId}/duplicate"
tags: ["Agents"]
---

# Copy an agent as a fresh draft

`POST /business/agents/{agentId}/duplicate`

## Request

- Base URL: `https://api.tryfuse.ai/api/v1`
- URL: `https://api.tryfuse.ai/api/v1/business/agents/{agentId}/duplicate`
- Auth: HTTP basic

Copies an agent of any status into a NEW draft named "<source name> (Copy)" (`status: initializing`, nothing billed). A draft source copies losslessly. A source that was started before configs were snapshotted is rebuilt from its live record, and every field that could not be recovered is listed in `lossyFields` — set those with PATCH before you activate the copy. This is also how you restart a paused agent, since `activate` only accepts drafts. The copy counts towards the free plan's 10-agent cap (403 AGENT_LIMIT_REACHED). Answers 201 with the new draft in the same shape as GET; activate it with POST /business/agents/{agentId}/activate using the returned `id`.

Errors:
- `404` `AGENT_NOT_FOUND` — No agent with this id belongs to the token owner. A deleted agent and another user's agent answer identically.
- `403` `AGENT_LIMIT_REACHED` — Free-plan accounts may hold at most 10 agents, drafts included. Delete an agent or upgrade the plan.
- `422` `VALIDATION_FAILED` — The request failed this endpoint's own validation — `param` names the offending field and `message` says why.
- `429` `RATE_LIMITED` — The agents bucket is exhausted: 30 requests per minute or 2,000 per day per token owner, shared by every /business/agents operation (a 429 raised by the agents service is relayed with this code too). Retry after the `Retry-After` header.
- `500` `UNEXPECTED_ERROR` — The agents service failed (5xx, refused service credential, or a timeout after 60s) or the rate limiter was unavailable. Retry later; quote `request_id` to support.

Requires one of the following token scopes: agents.

## Path parameters

- `agentId` string, required: The agent's id: a 24-character hex string — the `id` of an item from GET /business/agents, or the `agent.id` a create or duplicate returned.

## Response `201`

Success

- object
  - `agent` object, required
    - `id` string, required: The agent's id — pass it as `{agentId}` to every other agent operation.
    - `type` 'web-monitor' | 'person-starting-new-job' | 'linkedin-posts' | 'person-discovery-via-filters' | 'job-postings' | 'job-posting-in-location' | 'first-person-hired-in-company-department' | 'first-person-hired-internationally' | 'company-headcount-growth' | 'company-headcount-growth-over-baseline' | 'company-department-headcount' | 'company-employee-job-location-in-two-countries' | 'funding-announcements' | 'people-watcher' | 'companies-watcher' | 'job-changes-watcher' | 'linkedin-profile' | 'linkedin-post' | 'null', nullable, required: The public agent kind — the same slug you POST to at /business/agents/{type}. null for a legacy kind this API no longer offers.
    - `name` string, required: The agent's name, which is also the name of the results list it delivers into.
    - `status` 'initializing' | 'processing' | 'active' | 'paused' | 'expired' | 'failed' | 'completed' | 'deleted', required: initializing = saved draft, nothing billed; processing = a run is under way; active = running; paused = stopped by you; expired = past its expirationDate; failed = the provider setup failed. Older agents can also read `completed` (a one-off scrape that has finished) and `deleted` (an agent deleted before deletions were timestamped: still readable, but it can no longer be edited or activated).
    - `config` object, required: The agent's config in CREATE shape: exactly the body you would POST to /business/agents/{type} (without `start`) to build this agent again. Its fields are the ones documented on that type's create operation.
    - `isReconstructed` boolean, required: false = the config is the stored snapshot, returned verbatim (always the case for a draft). true = the agent was started before its snapshot existed and the config was rebuilt from the live record, so check `lossyFields`.
    - `lossyFields` string[], required: Config fields that could not be recovered when `isReconstructed` is true; `["*"]` means only `name` is known. Empty otherwise.
    - `sourceLists` object[], required: Watcher kinds only: the source lists the config names, resolved to their names. Empty for every other kind.
      - `id` string, required: The source list's id.
      - `name` string, nullable, required: The source list's name, or null when the list has been deleted.

## Other responses

- `400`: Error
- `401`: Error
- `402`: Error
- `403`: Error
- `404`: Error
- `409`: Error
- `422`: Error
- `429`: Error
- `500`: Error

---

[API](https://skmtc.dev/fuseai/apis/fuse-business-api.md) · [All operations](https://skmtc.dev/fuseai/apis/fuse-business-api/llms.txt) · [OpenAPI document](https://skmtc.dev/fuseai/apis/fuse-business-api/revisions/50d95e0536f4?raw)
