# Update a job

```http
PUT https://secure.yoprint.com/v2/api/store/{team_slug}/v2/job/{hash_id}
```

- API version: v2
- Operation ID: `v2_public_job_update`
- Section: Production › [Jobs](https://developer.yoprint.com/reference/jobs.md)
- Web page: https://developer.yoprint.com/reference/jobs/v2-job-update/
- Authentication: `Authorization: Bearer YOUR_API_KEY`

**Check `success`, not only the HTTP status:** when the job's order is neither a draft nor published, this call answers **HTTP 200** with `{ "status": 500, "success": false, "error": { "code": "action_not_allowed", "message": null } }` and changes nothing.

Changes a job's name, note, position or rush flag, and adds, changes or removes its services, tasks, mockups and production files in one call.

Send only what you change. Each of `service`, `pipeline`, `mockup` and `production_file` is a list of actions: every entry has an `action` of `create`, `update` or `delete`, and entries you leave out stay as they are.

Changing services (the decoration, its location, option or order) reprices the job and recalculates the sales order's totals. Other changes don't touch prices.

To change the status use Change a job's status; for the job number use Change a job number; for dates use Schedule a job. Returns the updated job.

## Permission

Needs permission to edit the job's sales order:
- the team owner;
- a role whose Manage Sales Orders permission is "update all";
- a role with "update assigned" when you created the order or are assigned to it; or
- on a draft order, its creator when their role can create sales orders.

Otherwise 403 `user_is_not_authorized`.

## Business rules

- The job's sales order must be a draft or published. Otherwise the reply is HTTP 200 with `success: false` and `error.code` `action_not_allowed` and nothing changes.
- Every list entry needs an `action`. `service` entries need `service_id`, `option`, `location` and `position` unless they delete.
- A task's `status_id` must belong to its `pipeline_id` (task preset).

## Side effects

- Changing services reprices the job and recalculates the order, its invoices and shipments that share pricing tiers.
- Turning `is_rush` on or off sends the `job.marked_as_rush` or `job.marked_as_not_rush` webhook.
- Deleting a mockup with `approval_request_action: remove_open_items` changes the job's open artwork approvals (see the field); Customer Portal pages the customer has open refresh for the approvals that remain.
- Open Admin Portal pages refresh.

## Path parameters

- `team_slug` (string, required): Your team slug, shown as Team ID next to your API key in Profile. Example `your-team`.
- `hash_id` (string, required): The job's hash id (`id`). Hash ids only: a unique key or a document number gives 404. Example `WaGvtaWsx7Kcn4`.

## Query parameters

- `omit_media_approval_items` (string, optional): Optional. `1` (or `true`, `yes`, `on`) makes the answer smaller: each mockup and production file's `current_approval` leaves out its `items` list, and every other key stays as it is. The job's `pending_approval` and webhook payloads keep their items. Every file repeats its approval with all of its items, so a job with many files on one approval answers with far less data this way; read approval items from the approvals operations instead. Left out (or any other value), the answer is unchanged. Only the query string is read: a body field with this name is ignored. Example `1`.

## Request body

Content type `application/json`, required.

Fields:

- `has_service` (boolean, optional): Accepted for older clients; it changes nothing.
- `is_rush` (boolean, optional): Marks the job as a rush job.
- `mockup` (array of objects, optional): Mockup actions. Mockups are uploaded files attached to the job.
  - Each item:
    - `action` (string, required): One of: `"create"`, `"update"`, `"delete"`.
    - `id` (string, required): The uploaded file (for `create`) or the mockup.
    - `approval_request_action` (string, optional): For `delete`: what to do with open artwork approvals that include this mockup. `remove_open_items` takes it out of every open approval of the job, and deletes each approval left with nothing to approve. With `keep` (the default) a mockup under an open approval stays in that approval. One of: `"keep"`, `"remove_open_items"`.
    - `job_service` (string | array, optional): The job service or services the mockup shows.
    - `name` (string, optional)
    - `position` (integer, optional): Required when `action` is `create`, but not used: YoPrint puts the new file last.
    - `show_in_pdf` (boolean, optional): Show it on the sales order PDF. Required unless `action` is `delete`.
- `name` (string, optional): The job name. A null is ignored (the name is kept).
- `note` (string, optional): The job note.
- `pipeline` (array of objects, optional): Task actions.
  - Each item:
    - `action` (string, required): One of: `"create"`, `"update"`, `"delete"`.
    - `assigned_users` (array of strings, optional): User hash ids to assign.
    - `due_date` (string (date-time) | null, optional): An ISO 8601 date or date-time, or null. Required (it may be null) when `action` is `create`.
    - `id` (string, optional): The task. Required unless `action` is `create`.
    - `name` (string, optional): The task name.
    - `pipeline_id` (string, optional): The task preset. Required unless `action` is `delete`.
    - `position` (integer, optional): Minimum -2147483648. Maximum 2147483647.
    - `start_date` (string (date-time) | null, optional): An ISO 8601 date or date-time, or null. Required (it may be null) when `action` is `create`.
    - `status_id` (string, optional): A status of that task preset. Required unless `action` is `delete`.
    - `unassigned_users` (array of strings, optional): User hash ids to unassign (`update` only).
- `position` (integer, optional): The job's place among the order's jobs. To reorder every job safely, use Reorder the jobs of a sales order or quote. Minimum -2147483648. Maximum 2147483647.
- `production_file` (array of objects, optional): Production file actions.
  - Each item:
    - `action` (string, required): One of: `"create"`, `"update"`, `"delete"`.
    - `id` (string, required): The uploaded file (for `create`) or the production file.
    - `job_service` (string | array, optional): The job service or services the file is for.
    - `position` (integer, optional): Required when `action` is `create`, but not used: YoPrint puts the new file last.
- `scoped_id` (string, optional): Accepted but ignored here. Use Change a job number.
- `service` (array of objects, optional): Service actions (the decorations on the job).
  - Each item:
    - `action` (string, required): One of: `"create"`, `"update"`, `"delete"`.
    - `id` (string, required): Required for every action. For `update` and `delete`, the job service's hash id. For `create`, a temporary id you choose that starts with `tmpid-` (`tmpid-1`); `mockup` and `production_file` entries in the same call can name it in `job_service`. Any other made-up value fails as a bad hash id.
    - `customer_note` (string, optional): Customer notes.
    - `location` (object, optional): Where the service goes. Required unless `action` is `delete`.
      - `id` (string, optional): The saved location. Required when `type` is `database`.
      - `name` (string, optional): The location name. Required when `type` is `custom`.
      - `type` (string, optional): `database` for one of your saved locations, `custom` for a name you type. One of: `"database"`, `"custom"`.
    - `note` (string, optional): Internal notes.
    - `option` (any, optional): The service option, as your service defines it. Required unless `action` is `delete`.
    - `position` (integer, optional): Order of the service on the job. Required unless `action` is `delete`. Minimum -2147483648. Maximum 2147483647.
    - `service_id` (string, optional): The service from your team's services. Required unless `action` is `delete`.

### Example request

```bash
curl -X PUT 'https://secure.yoprint.com/v2/api/store/your-team/v2/job/WaGvtaWsx7Kcn4' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Accept: application/json' \
  -H 'X-Yoprint-Decimal-Format: exact-v1' \
  -H 'Content-Type: application/json' \
  -d '{
    "pipeline": [
      {
        "action": "create",
        "assigned_users": [
          "4mdDkMg3dgQOa3"
        ],
        "due_date": "2026-11-05T17:00:00Z",
        "name": "Burn screens",
        "pipeline_id": "SE3SfXjt6dPfnH",
        "start_date": "2026-11-04T09:00:00Z",
        "status_id": "hTFITko5Q0R83y"
      }
    ]
  }'
```

Another example: Rename a job and mark it rush:

```bash
curl -X PUT 'https://secure.yoprint.com/v2/api/store/your-team/v2/job/WaGvtaWsx7Kcn4' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Accept: application/json' \
  -H 'X-Yoprint-Decimal-Format: exact-v1' \
  -H 'Content-Type: application/json' \
  -d '{
    "is_rush": true,
    "name": "Front and back print"
  }'
```

## Response

`200` Successful response.

> **Warning: a 200 answer can still be a refusal.** Check `success` (and the fields named below) as well as the HTTP status.
> - The order is neither a draft nor published (`success: false`, `action_not_allowed`). Fix: Check `success` in every reply, not only the HTTP status.

Refusal example (Refused with HTTP 200: `success` is false):

```json
{
  "error": {
    "code": "action_not_allowed",
    "message": null
  },
  "status": 500,
  "success": false
}
```

Example response:

```json
{
  "data": {
    "assigned_users": [],
    "customer": {
      "id": "ifAHmADekGZ6id",
      "name": "Northwind Apparel"
    },
    "due_date": "2026-11-06T17:00:00+00:00",
    "id": "WaGvtaWsx7Kcn4",
    "is_rush": true,
    "item_count": 48,
    "mockup": [],
    "name": "Front and back print",
    "note": null,
    "order_id": "sFbALVSYD55eXe",
    "order_scoped_id": "SO1001",
    "pdf": [
      {
        "description": "Job details without mockup",
        "label": "Job Details",
        "url": "https://example.com/pdf/job-details.pdf"
      }
    ],
    "pipelines": [
      {
        "assigned_users": [
          {
            "avatar_url": null,
            "id": "4mdDkMg3dgQOa3",
            "name": "Alex Rivera"
          }
        ],
        "created_at": "2026-11-03T15:00:00+00:00",
        "due_date": "2026-11-05T17:00:00+00:00",
        "id": "hpioY1gDBQZdbI",
        "job_id": "WaGvtaWsx7Kcn4",
        "job_is_rush": 1,
        "job_item_count": 48,
        "job_name": "Front print",
        "job_scoped_id": "JOB-2419",
        "job_status_id": "scaWHQnPLtqMPT",
        "name": "Burn screens",
        "note": null,
        "order_id": "sFbALVSYD55eXe",
        "order_name": "Team shirts",
        "order_scoped_id": "SO1001",
        "pipeline_id": "SE3SfXjt6dPfnH",
        "position": 1,
        "sales_order": {
          "customer_id": "ifAHmADekGZ6id",
          "customer_name": "Northwind Apparel",
          "is_quote": false,
          "object_type": "sales_order",
          "status_id": "wgbOT87gGZvhgy"
        },
        "start_date": "2026-11-04T09:00:00+00:00",
        "status": {
          "color": "#2196f3",
          "customer_label": "In Progress",
          "id": "hTFITko5Q0R83y",
          "label": "Burning",
          "pipeline_id": "SE3SfXjt6dPfnH",
          "position": 2,
          "role": "pipeline",
          "trashed": false,
          "type": "in_progress"
        },
        "status_completion_date": null,
        "status_id": "hTFITko5Q0R83y",
        "status_last_change_date": "2026-11-03T15:05:00+00:00",
        "updated_at": "2026-11-03T15:05:00+00:00"
      }
    ],
    "position": 1,
    "pricing_original_total": {
      "dp": 6,
      "value": 600000000
    },
    "pricing_rule_applied": null,
    "pricing_total": {
      "dp": 6,
      "value": 600000000
    },
    "production_file": [],
    "sales_order": {
      "is_quote": false,
      "is_rush": false,
      "name": "Team shirts",
      "object_type": "sales_order",
      "status_id": "wgbOT87gGZvhgy"
    },
    "scoped_id": "JOB-2419",
    "services": [
      {
        "id": "tCBpDSBjXaPhHN",
        "option": "2",
        "position": 1,
        "service_id": "5Sf6XRMN2Vuxvh",
        "service_name": "Screen print"
      }
    ],
    "start_date": "2026-11-04T09:00:00+00:00",
    "status": {
      "color": "#2196f3",
      "customer_label": "In Progress",
      "id": "scaWHQnPLtqMPT",
      "label": "Printing",
      "position": 3,
      "role": "job",
      "trashed": false,
      "type": "in_progress"
    },
    "status_completion_date": null,
    "status_id": "scaWHQnPLtqMPT",
    "status_last_change_date": "2026-11-03T15:05:00+00:00",
    "total_qty_need_ordering": "0.00000000",
    "unique_key": "job_EXAMPLEuniqueKey"
  },
  "status": 200,
  "success": true
}
```

## Errors

- `401` The API key is missing or wrong (`unauthenticated`).
- `403` You are not allowed to do this. `api_access_not_in_plan`: your team's plan doesn't include API access (Pro and above, with an active subscription or trial), so every request answers this until the team upgrades. When your role lacks the permission the operation needs, the body is only `{"message": "Insufficient Permission"}`. Other refusals use the error envelope, with `unauthorized` or `user_is_not_authorized`.
  - When: Your role can't edit this order (`user_is_not_authorized`). Fix: Ask the team owner to adjust your role or assign you to the order.
- `404` Not found. `page_not_found`: the team slug is unknown, you are not a member of the team, or an id in the path is not one of this team's. `code: null`, with a message that starts "No query results for": there is no record with that id.
  - When: The job isn't your team's, its order is an old (version 1) order, or an entry's `id` (task, mockup, production file) isn't on this job. Jobs on quotes work too. Fix: Use the job's hash id (`id`) from the order's job list; unique keys don't work in this path.
- `422` The request was refused and changed nothing. `validation_failed` lists what to fix in `error.fields`; other codes name a business rule, explained in `error.message`. A few checks answer with only `{"message": "..."}`. An operation that calls another service (a payment provider, a carrier, an accounting app) can answer `connect_timeout` ("Please retry again") when that service does not answer in time: the change may or may not have happened there, so read the record back before you retry.
  - When: A list entry breaks its field rules (for example a service without `location.type`): `validation_failed`. Fix: Read `error.fields` and resend the entries.
  - When: A service, option, task preset or task status is not valid, a task gets only one of its two dates, or a file wasn't uploaded first: `job_validation_error`, with the reason in `error.message` and no `error.fields`. Fix: Correct that entry and resend.

## Notes

- A refusal here is HTTP 200 with `success: false` and `error.code` `action_not_allowed` (the body's `status` says 500). A client that only checks the HTTP status will treat it as done.
- Do not send `status_id` here. Use Change a job's status, which checks the status and sends the status webhook.
- Mockup and production file `create` entries take the hash id of a file you uploaded first with the async upload (`v1.public.async_upload.store`); any other id is a 422.

## Related

- [Get one job of an order](https://developer.yoprint.com/reference/jobs/v2-job-show.md): `GET /v2/api/store/{team_slug}/v2/sales_order/{hash_id}/job/{job_id}`
- [Change a job's status](https://developer.yoprint.com/reference/jobs/v2-job-change-status.md): `PUT /v2/api/store/{team_slug}/v2/job/{hash_id}/status`
- [Change a job number](https://developer.yoprint.com/reference/jobs/v2-job-update-scoped-id.md): `PUT /v2/api/store/{team_slug}/v2/job/{hash_id}/scoped_id`
- [Schedule a job](https://developer.yoprint.com/reference/jobs/v2-job-update-prod-date.md): `PUT /v2/api/store/{team_slug}/v2/job/{hash_id}/update_prod_date`
- [Reorder the jobs of a sales order or quote](https://developer.yoprint.com/reference/jobs/v2-job-rearrange.md): `PUT /v2/api/store/{team_slug}/v2/sales_order/{hash_id}/job/rearrange`
