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

# Create or Update Project

> Create a new Project or update an existing Project's settings

Programmatically create new Projects or update existing ones. Projects are the
top-level container in DNCScrub for organizing campaigns, scrub options, and
Internal DNC lists.

If the supplied `project_code` already exists, the endpoint updates the
existing Project. If it does not exist, a new Project is created with a
default Campaign.

## Request

### Headers

<ParamField header="loginId" type="string" required>
  Your API Key
</ParamField>

### Query / Form Parameters

<ParamField query="project_code" type="string" required>
  Project code to insert or update. Will be uppercased and trimmed.

  If your account has auto-prefixing enabled, the prefix `<acctId>_` is added
  automatically when missing.

  Pass `projId=<acctId>` instead of `project_code` to operate on the Master
  Project.
</ParamField>

<ParamField query="project_name" type="string" required>
  Display name of the Project.
</ParamField>

<ParamField query="nat_dnc_org_id" type="string">
  FTC Org Id or SAN. When supplied on a new Project, the value is validated
  against the FTC; if a SAN is supplied, the corresponding Org Id is resolved
  and stored.
</ParamField>

<ParamField query="handler" type="string">
  Internal handler override. The endpoint normally infers this:

  * `insert_project` - new project (auto-selected when `project_code` does not exist)
  * `update_project` - update existing project (auto-selected when it exists)
  * `deactivate_project` - mark project inactive
  * `reactivate_project` - reactivate an inactive project
</ParamField>

<ParamField query="output" type="string">
  Pass `xml` to return a full XML document describing the resulting Project,
  its Campaigns, and (for SmartBlock-enabled accounts) SmartBlock settings.
</ParamField>

<ParamField query="notes" type="string">
  Free-form project notes.
</ParamField>

<ParamField query="use_master_dnc_dnm_database" type="boolean">
  Inherit the Master Project's Internal DNC / DNM database.
</ParamField>

<ParamField query="use_master_override_database" type="boolean">
  Inherit the Master Project's EBR / override database.
</ParamField>

<ParamField query="use_master_policy" type="boolean">
  Inherit the Master Project's DNC policy.
</ParamField>

<ParamField query="use_master_nat_sub" type="boolean">
  Inherit the Master Project's national DNC subscription.
</ParamField>

<ParamField query="use_master_training" type="boolean">
  Inherit the Master Project's training materials.
</ParamField>

## Example Request

<CodeGroup>
  ```bash cURL (Create) theme={null}
  curl --location --request POST \
    'https://www.dncscrub.com/app/main/rpc/project' \
    --header 'loginId: YOUR_API_KEY' \
    --data-urlencode 'project_code=ACME_Q4' \
    --data-urlencode 'project_name=ACME Q4 Outbound' \
    --data-urlencode 'nat_dnc_org_id=12345678'
  ```

  ```bash cURL (Update) theme={null}
  curl --location --request POST \
    'https://www.dncscrub.com/app/main/rpc/project' \
    --header 'loginId: YOUR_API_KEY' \
    --data-urlencode 'project_code=ACME_Q4' \
    --data-urlencode 'project_name=ACME Q4 (renamed)'
  ```

  ```bash cURL (Create + XML response) theme={null}
  curl --location --request POST \
    'https://www.dncscrub.com/app/main/rpc/project?output=xml' \
    --header 'loginId: YOUR_API_KEY' \
    --data-urlencode 'project_code=ACME_Q4' \
    --data-urlencode 'project_name=ACME Q4 Outbound'
  ```

  ```javascript JavaScript theme={null}
  const body = new URLSearchParams({
    project_code: "ACME_Q4",
    project_name: "ACME Q4 Outbound",
    nat_dnc_org_id: "12345678",
  });

  const res = await fetch("https://www.dncscrub.com/app/main/rpc/project", {
    method: "POST",
    headers: {
      loginId: "YOUR_API_KEY",
      "Content-Type": "application/x-www-form-urlencoded",
    },
    body,
  });

  console.log(res.status); // 201 on create, 200 on update
  ```

  ```csharp C# theme={null}
  using (var client = new HttpClient())
  {
      client.DefaultRequestHeaders.Add("loginId", "YOUR_API_KEY");

      var form = new FormUrlEncodedContent(new[]
      {
          new KeyValuePair<string, string>("project_code", "ACME_Q4"),
          new KeyValuePair<string, string>("project_name", "ACME Q4 Outbound"),
          new KeyValuePair<string, string>("nat_dnc_org_id", "12345678"),
      });

      var res = await client.PostAsync(
          "https://www.dncscrub.com/app/main/rpc/project", form);
  }
  ```
</CodeGroup>

## Response

| Status Code | Meaning                                                             |
| ----------- | ------------------------------------------------------------------- |
| `200`       | Project updated successfully (no body unless `output=xml`)          |
| `201`       | Project created successfully (no body unless `output=xml`)          |
| `400`       | Validation or save error - reason phrase contains the error message |
| `403`       | Project exists but is inactive (use `handler=reactivate_project`)   |

When `output=xml` is supplied, the response body is an XML document rooted at
`<DncCompliance><DncScrub><Accounts><Account><Projects>...</Projects></Account></Accounts></DncScrub></DncCompliance>`
containing the Project, its Campaigns, and any FTC Org Id metadata that was
just resolved.

## Reactivating an Inactive Project

If `project_code` matches an inactive Project, the endpoint returns `403
Inactive Project` unless you explicitly request reactivation:

```bash theme={null}
curl --location --request POST \
  'https://www.dncscrub.com/app/main/rpc/project' \
  --header 'loginId: YOUR_API_KEY' \
  --data-urlencode 'project_code=ACME_Q4' \
  --data-urlencode 'project_name=ACME Q4 Outbound' \
  --data-urlencode 'handler=reactivate_project'
```

## Master Project Operations

Pass `projId=<acctId>` (with no `project_code`) to update settings on your
account's Master Project:

```bash theme={null}
curl --location --request POST \
  'https://www.dncscrub.com/app/main/rpc/project' \
  --header 'loginId: YOUR_API_KEY' \
  --data-urlencode 'projId=YOUR_ACCT_ID' \
  --data-urlencode 'nat_dnc_org_id=12345678'
```

## Listing All Projects

There is no separate list endpoint - this same endpoint returns a full project
enumeration when you target the Master Project with `output=xml` and no fields
to update. Because no fields change, the call is read-only:

```bash theme={null}
curl --location --request GET \
  'https://www.dncscrub.com/app/main/rpc/project?projId=YOUR_ACCT_ID&output=xml' \
  --header 'loginId: YOUR_API_KEY'
```

The XML response lists every Project the account can access (including
cross-account projects), each Project's Campaigns, and each Campaign's status.
To list a single Project instead, pass that Project's `projId` rather than your
account ID.

To get details for a single Project, pass that Project's `projId`:

```bash theme={null}
curl --location --request GET \
  'https://www.dncscrub.com/app/main/rpc/project?projId=ACME_Q4&output=xml' \
  --header 'loginId: YOUR_API_KEY'
```

## Best Practices

<AccordionGroup>
  <Accordion title="Idempotent Upserts">
    The same request creates a Project on first call and updates it on
    subsequent calls. Use the HTTP status code (`201` vs `200`) to tell the
    cases apart.
  </Accordion>

  <Accordion title="Use output=xml on Create">
    Adding `output=xml` to a create request returns the new Project's full
    record (including the auto-created default Campaign) so you don't need a
    follow-up call to get its IDs.
  </Accordion>

  <Accordion title="FTC Org Id Validation">
    Supplying `nat_dnc_org_id` on a new Project triggers FTC validation. Make
    sure the Org Id (or SAN) is correct, or the create will fail with an FTC
    error message.
  </Accordion>

  <Accordion title="Project Code Rules">
    Project codes are uppercased automatically. Avoid the `_` character in your
    raw code if your account uses auto-prefixing - the prefix delimiter is
    `_`.
  </Accordion>
</AccordionGroup>
