---
title: "Set up Ticket to PR"
method: POST
path: "/experimental/projects/{projectId}/factory/ticket-to-pr"
tags: ["Projects", "Schedules"]
---

# Set up Ticket to PR

`POST /experimental/projects/{projectId}/factory/ticket-to-pr`

## Request

- Base URL: `https://api.tessl.io`
- URL: `https://api.tessl.io/experimental/projects/{projectId}/factory/ticket-to-pr`
- Auth: none declared

Sets up the three factory Loops of Ticket to PR for a root GitHub project: Implement, Shepherd and Follow ticket changes, which run skills from `tessl-labs/factory`. A Loop counts as set up when a live Loop of the project, app- or repo-defined, already runs the same skill on the same triggers; the request creates only the others, so a second request creates nothing. Every check runs before anything is written, and the environments and Loops are written in one transaction, so a refusal leaves none of them. The issue source defaults to Linear, which needs a Linear connection with a Linear team routed to the project. The GitHub source starts on GitHub issues labelled in the project repository, and creates the label when it is missing. When the project already has a live ticket intake Loop, the oldest Loop whose triggers start on a GitHub issue label or a Linear issue delegated to Tessl, setup keeps it as Implement with its source, and for GitHub its label, whatever the request asks for, so it never adds a second Loop that takes tickets. Either source needs the Tessl App on the project repository.

## Path parameters

- `projectId` string, uuid, required

## Headers

- `Authorization` string

## Request body

- object
  - `issueSource` object
    - `type` union, required
      - 'linear'
      - 'github'
    - `label` string: GitHub source only: the issue label that hands an issue to Tessl. Defaults to `tessl`.

## Response `201`

Default Response

- object
  - `links` object, required
    - `self` string, uri, required
  - `data` object, required
    - `id` string, uuid, required
    - `type` 'project', required
    - `attributes` object, required
      - `loops` object[], required
        - `stage` union, required
          - 'implement'
          - 'shepherd'
          - 'follow-ticket-changes'
        - `id` string, uuid, required
        - `created` boolean, required: Whether this request created the Loop. False when the project already had it.

## Other responses

- `400`: Bad Request
- `401`: Unauthorized
- `403`: Default Response
- `404`: Not Found
- `409`: Default Response
- `500`: Internal Server Error
- `501`: Not Implemented

## Changes

- **2026-10-29** `06d2142ed144`: 1 info
  - api operation id `createProjectFactoryTicketToPr` was added
- **2026-10-22** `d97810390526`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/tessl/apis/tessl-api/changes/experimental/projects/:projectId/factory/ticket-to-pr/post.md)

---

[API](https://skmtc.dev/tessl/apis/tessl-api.md) - [All operations](https://skmtc.dev/tessl/apis/tessl-api/llms.txt) - [OpenAPI document](https://skmtc.dev/tessl/apis/tessl-api/revisions/4fa2a17154e4?raw)
