# Creating and updating data

Changes go through mutations. Every object has a create and an update mutation that work the same way, and deleting is an update too. Changes made through the API show up in the app straight away, for everyone on the team.

URL: https://www.success.co/docs/guides/api-creating-and-updating-data  
Published: 2026-11-12

## Create an item

Create mutations are named `create` plus the object: `createTodo`, `createIssue`, `createRock`. The new item's fields go inside `input`, under the object's name, and you choose which fields of the new item to get back:

```graphql
mutation AddTodo($todo: TodoInput!) {
  createTodo(input: { todo: $todo }) {
    todo {
      id
      name
      dueDate
    }
  }
}
```

```json
{
  "todo": {
    "name": "Send the Q4 board pack",
    "desc": "",
    "teamId": "0b7e5f6a-3c2d-4e1f-9a8b-7c6d5e4f3a21",
    "userId": "5f2d8c4b-1a3e-4c7d-b9f0-2e6a7d8c9b10",
    "todoStatusId": "TODO",
    "priorityNo": 999,
    "dueDate": "2026-11-20",
    "companyId": "6a1d4e2b-7c3f-4a8e-b5d9-0f1e2d3c4b5a"
  }
}
```

A few things every create needs:

- **`companyId`** on every new item. Get it once with `query { currentCompanyId }` or from the **API Keys** page.
- **The owner and team**, as IDs (`userId`, `teamId`). Look them up with `users` and `teams` queries.
- **The object's required fields.** The [Data model](https://www.success.co/docs/guides/api-data-model) guide lists them for each object, and the error message names any you've missed.

Leave out `id`, `createdAt` and `stateId`, and they're filled in for you. You can set `id` yourself (any UUID) when you want to refer to the new item in the same request; see [Make several changes at once](#make-several-changes-at-once).

## Update an item

Update mutations are named `update` plus the object. Pass the item's `id`, and in `patch` only the fields you want to change. Everything else stays as it is:

```graphql
mutation MarkTodoDone($id: UUID!) {
  updateTodo(input: { id: $id, patch: { todoStatusId: "COMPLETE" } }) {
    todo { id name todoStatusId }
  }
}
```

Some common updates:

| To do this | Patch |
| --- | --- |
| Mark a To-do done | `updateTodo` with `{ todoStatusId: "COMPLETE" }` |
| Solve an Issue | `updateIssue` with `{ issueStatusId: "COMPLETE" }` |
| Set a Rock off-track | `updateRock` with `{ rockStatusId: "OFFTRACK" }` |
| Move an Issue to another team | `updateIssue` with `{ teamId: "..." }` |
| Change a due date | `{ dueDate: "2026-12-05" }` |
| Hand an item to someone else | `{ userId: "..." }` |

When you change a status, also set `statusUpdatedAt` to the current time, as the app does. Success.co uses it for things like when a To-do was completed, and it isn't updated for you:

```graphql
mutation MarkTodoDone($id: UUID!, $now: Datetime!) {
  updateTodo(input: { id: $id, patch: { todoStatusId: "COMPLETE", statusUpdatedAt: $now } }) {
    todo { id todoStatusId statusUpdatedAt }
  }
}
```

## Delete an item

Rocks, To-dos, Issues, Headlines, Milestones, Scorecard measurables and values, comments and the other main objects don't have delete mutations. Deleting one is an update that sets `stateId` to `DELETED`, exactly what the app does when someone clicks **Delete**:

```graphql
mutation DeleteIssue($id: String!) {
  updateIssue(input: { id: $id, patch: { stateId: "DELETED" } }) {
    issue { id stateId }
  }
}
```

The item disappears from the app but stays in the API with `stateId: "DELETED"`, which is why list queries should filter on `stateId: { equalTo: "ACTIVE" }`. To restore it, set `stateId` back to `ACTIVE`.

A few linking records (such as which teams a process is shared with) do have `delete` mutations, and those remove the record for good.

## Make several changes at once

You can put more than one mutation in a request. Give each an alias so you can tell the answers apart:

```graphql
mutation {
  first: updateTodo(input: { id: "3f1c...", patch: { todoStatusId: "COMPLETE" } }) { todo { id } }
  second: updateTodo(input: { id: "9a4e...", patch: { todoStatusId: "COMPLETE" } }) { todo { id } }
}
```

The mutations in one request run as a single unit: if any of them fails, none of them are saved. That makes it safe to create things that belong together, like a Rock and its link to a team. Choose the Rock's `id` yourself (a fresh UUID) so the second mutation can refer to it:

```graphql
mutation AddRock($rockId: UUID!, $teamId: UUID!, $userId: UUID!, $companyId: UUID!) {
  createRock(
    input: {
      rock: {
        id: $rockId
        name: "Launch the partner program"
        desc: ""
        type: "company"
        rockStatusId: "ONTRACK"
        dueDate: "2026-12-31"
        userId: $userId
        companyId: $companyId
      }
    }
  ) {
    rock { id }
  }
  createTeamsOnRock(
    input: { teamsOnRock: { rockId: $rockId, teamId: $teamId, companyId: $companyId } }
  ) {
    teamsOnRock { id }
  }
}
```

In JavaScript, `crypto.randomUUID()` makes a UUID; in Python, `str(uuid.uuid4())`.

## Who made the change

Changes are made as the person who owns the API key. The app shows them as that person's, and `lastUpdatedByUserId` on the item records it. If your integration makes a lot of changes, consider creating a separate Success.co user for it (for example "Finance sync", which counts as a user on your plan) and making its key there, so its changes are easy to tell apart from yours. It also keeps the integration running if you leave: a key stops working when its owner is deactivated, so an integration that runs on a person's key stops when they do. Keep that user active for as long as the integration runs.

> **Note:** **Test on a copy first.** There's no undo for changes made through the API, apart from setting them back yourself. Try new scripts against a test company, or on a team set up for testing, before pointing them at your real data.
