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

# Merge

> Merge changes between branches without cloning the repository or shelling out to Git. This endpoint also supports promoting work from ephemeral branches into long-lived branches such as `main`. Omit `expected_target_sha` to merge into the current target tip and allow the gateway to retry stale target/repository movement internally; set `expected_target_sha` to require a strict target-tip precondition. GitHub-backed public targets currently do not use automatic retry.
#### JWT claims
Required scopes: `git:write`  
Requires per repo scope: Yes



## OpenAPI

````yaml openapi.json POST /api/repos/{repo_name}/merge
openapi: 3.1.0
info:
  description: >-
    The Code Storage HTTP API exposes repository management, Git reads, and
    write workflows over plain HTTPS.


    ## Authentication


    Send a signed JWT in the `Authorization: Bearer <token>` header on every
    request.


    - Organisation-scoped endpoints such as `GET /api/repos` require
    organisation scopes like `org:read`

    - Repository-scoped endpoints require a JWT whose `repo` claim names the
    target repository

    - Write operations require the relevant scope such as `git:write` or
    `repo:write`


    ## Pagination


    List endpoints use cursor-based pagination.


    - `cursor` is an opaque token returned by the previous response

    - `limit` defaults to `20` and is capped per endpoint

    - `has_more` tells you whether another request is available

    - `next_cursor` becomes the next `cursor` value


    ## Paths


    Preferred routes use the shorter `/api/...` form. Legacy `/api/v1/...`
    aliases remain documented where they are still supported and are marked as
    deprecated when a preferred route exists.


    ## Repository names in paths


    - Names containing `/` (or any other character that is not safe in a URL
    path segment) **must** be URL encoded so the value occupies a single path
    segment. For example, `pierre/example` becomes `pierre%2Fexample` and the
    request URL is `/api/repos/pierre%2Fexample/...`.

    - Plain names that contain only URL-safe characters can be sent as-is:
    `/api/repos/dotfiles/...`.

    - The server URL-decodes the value before resolving the repository, so
    double-encoding is not required.


    ## Errors


    Most endpoints return RFC 9457-compatible problem details under
    `application/problem+json`, with a legacy `error` field mirrored from
    `detail`. Each problem body has a stable, snake_case `code`. Branch on
    `code`, not on `detail`. The Error codes section lists the values.


    A `429 Too Many Requests` response carries the current IETF `RateLimit`
    service-limit field and `Retry-After`. `RateLimit` reports immediately
    available quota (`r`) and its effective window in seconds (`t`);
    `Retry-After` is the minimum delay and takes precedence. The gateway's
    capacity is dynamic, so it does not advertise a fixed `RateLimit-Policy` on
    successful responses.


    Streaming commit and note workflows may return operation-specific failure
    bodies so callers can inspect partial results, branch state, or workflow
    status without parsing generic error strings.


    ## Error codes


    Each problem body has a stable `code`. Each status has a generic code. A
    specific code replaces it when the caller must take a different action. New
    codes can be added. Treat an unknown code as the generic code for its
    status.


    Generic codes: `bad_request` (400), `unauthorized` (401), `forbidden` (403),
    `not_found` (404), `method_not_allowed` (405), `request_timeout` (408),
    `conflict` (409), `precondition_failed` (412), `payload_too_large` (413),
    `unprocessable_entity` (422), `rate_limited` (429), `request_canceled`
    (499), `internal_error` (500), `not_implemented` (501), `bad_gateway` (502),
    `service_unavailable` (503), `gateway_timeout` (504). Any other status uses
    its status text in snake_case.


    Specific codes:


    - `authentication_unavailable` (403): the server cannot verify credentials
    now; retry.

    - `insufficient_scope` (403): the token does not have a scope that the
    operation requires.

    - `repo_claim_missing` (400): the token has no `repo` claim.

    - `repo_name_mismatch` (400): the request `repo_name` does not match the
    token `repo` claim.

    - `route_not_found` (404): no API route matches the path.

    - `repository_not_found` (404): the repository does not exist or the token
    cannot access it.

    - `repository_deleted` (409): the repository is already deleted.

    - `repository_thawing` (409): the repository is being restored from cold
    storage; retry after `Retry-After`.

    - `sync_in_progress` (409): an upstream sync is in progress; retry.

    - `upstream_already_configured` (409): the repository already has an
    upstream.

    - `branch_not_found` (404): the branch does not exist.

    - `ref_not_found` (404): the ref or revision does not exist.

    - `merge_conflict` (409): the merge has file conflicts.

    - `credential_not_found` (404): the Git credential does not exist.

    - `credential_exists` (409): the repository already has a Git credential.

    - `github_app_not_configured` (412): the organization does not have exactly
    one GitHub App.

    - `github_repository_inaccessible` (412, or the 4xx status from the
    upstream): GitHub does not give access to the upstream repository.

    - `hosting_not_enabled` (403): hosting is not enabled for the organization.

    - `hosting_project_not_found` (404): the repository has no hosting project.

    - `deployment_not_found` (404): the deployment does not exist.

    - `deployment_project_name_in_use` (409): another repository uses the
    hosting project name.

    - `idempotency_key_reused` (422): the idempotency key belongs to a different
    request.
  title: code.storage
  version: 1.0.0
servers:
  - description: Code Storage API host for your organization
    url: https://api.{org}.code.storage
    variables:
      org:
        default: your-org
        description: >-
          The subdomain of your API host. It is usually your organization name.
          The organization settings page in the dashboard shows your exact API
          host.
security: []
tags:
  - description: >-
      Create, inspect, update, delete, and synchronise repositories, including
      upstream pull-sync and generic HTTPS Git credentials for non-GitHub
      upstreams.
    name: Repositories
  - description: Create, delete, list, and compare branches.
    name: Branches
  - description: >-
      Read commit metadata and diffs, or create commits without a local Git
      client.
    name: Commits
  - description: >-
      Read repository trees, file contents, archives, and server-side search
      results.
    name: Files
  - description: List, create, and delete Git tags.
    name: Tags
  - description: Attach and retrieve Git notes for commits or other Git objects.
    name: Notes
  - description: >-
      Read metadata about the Code Storage deployment that serves your
      organisation, such as its cloud location and inbound IP addresses.
    name: Organization
paths:
  /api/repos/{repo_name}/merge:
    post:
      tags:
        - Branches
      summary: Merge Branch
      description: >-
        Merge changes between branches without cloning the repository or
        shelling out to Git. This endpoint also supports promoting work from
        ephemeral branches into long-lived branches such as `main`. Omit
        `expected_target_sha` to merge into the current target tip and allow the
        gateway to retry stale target/repository movement internally; set
        `expected_target_sha` to require a strict target-tip precondition.
        GitHub-backed public targets currently do not use automatic retry.

        #### JWT claims

        Required scopes: `git:write`  

        Requires per repo scope: Yes
      operationId: repos-merge
      parameters:
        - description: >-
            Repository name. Names that contain `/` or any other character that
            is not safe in a URL path segment must be URL encoded so the value
            occupies a single path segment. For example `pierre/example` is sent
            as `pierre%2Fexample`. Plain names such as `example` can be sent
            as-is. The server URL-decodes the value before resolving the
            repository.
          example: my-demo-repository
          in: path
          name: repo_name
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            example:
              author:
                email: review@example.com
                name: Review Bot
              commit_message: Merge feature/preview
              committer:
                email: review@example.com
                name: Review Bot
              expected_target_sha: c4f0fdfc41adab56630b34f5f4fd4e84a2c5b4d2
              source_branch: feature/preview
              source_is_ephemeral: true
              source_ref: feature/preview
              squash: false
              strategy: merge
              target_branch: main
            schema:
              $ref: '#/components/schemas/ReposMergeRequest'
        description: >-
          Merge a source branch into a target branch using a merge commit,
          fast-forward only, or fast-forward preferred behaviour. Source and
          target can live in the default or ephemeral namespace. When
          expected_target_sha is omitted, the gateway may retry stale target
          updates internally while keeping the originally resolved source commit
          pinned. Automatic stale-target retry is disabled for GitHub-backed
          public targets.
        required: true
      responses:
        '200':
          content:
            application/json:
              example:
                commit_sha: 41f0d5c6cc5f4d0fb4a3af2de27ccf9a80ab3b84
                merge_base_sha: a2d127e6a4d54bb7390de828a99e36411f0c84df
                promoted_commits: 3
                result: merged
                source:
                  branch: feature/preview
                  ephemeral: true
                  ref: feature/preview
                  sha: 9eb378bdb5bf1944f6ba0bd5a2c4df3ce32f4df1
                target:
                  branch: main
                  new_sha: 41f0d5c6cc5f4d0fb4a3af2de27ccf9a80ab3b84
                  old_sha: c4f0fdfc41adab56630b34f5f4fd4e84a2c5b4d2
                tree_sha: b9532c5d5be50d88e2f45d7c229566b2f1f99731
              schema:
                $ref: '#/components/schemas/ReposMergeResponse'
          description: >-
            Merge result, including the source and target commit state after the
            operation.
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
          description: Bad Request
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
          description: Forbidden
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
          description: Not Found
        '409':
          content:
            application/json:
              example:
                conflict_type: merge_conflict
                error: merge conflict
              schema:
                $ref: '#/components/schemas/MergeConflict'
          description: >-
            The merge could not be completed because of file-level conflicts, or
            an automatic stale-target retry could not absorb concurrent
            target/repository movement. Inspect conflict_type to distinguish
            merge_conflict, target_moved, and repo_changed.
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
          description: Too Many Requests
          headers:
            RateLimit:
              description: >-
                Current IETF service-limit field. `r=0` means no request is
                immediately available; `t` is the effective window in seconds
                before capacity is expected to return.
              schema:
                type: string
            Retry-After:
              description: >-
                Minimum delay before retrying, expressed as seconds or an HTTP
                date. This value takes precedence over the `RateLimit` effective
                window.
              schema:
                type: string
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
          description: Internal Server Error
        '503':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
          description: Service Unavailable
      security:
        - bearerAuth:
            - git:write
components:
  schemas:
    ReposMergeRequest:
      additionalProperties: false
      description: >-
        Merge request body specifying source and target branches, optional
        pinned source SHA, merge strategy, optional squash flag, and optional
        retry-on-target-move behavior, which is currently unsupported for
        GitHub-backed public targets.
      properties:
        allow_unrelated_histories:
          description: Permit merges between unrelated histories.
          type: boolean
        author:
          $ref: '#/components/schemas/GitIdentity'
          description: >-
            Author identity used when the backend creates a merge commit.
            Required for merge-commit strategies.
        commit_message:
          description: Commit message used when a merge commit is created.
          examples:
            - Merge feature/preview
          type: string
        committer:
          $ref: '#/components/schemas/GitIdentity'
          description: >-
            Committer identity for the merge commit. Defaults to author when
            omitted.
        expected_target_sha:
          description: >-
            Optional branch tip guard. The merge fails if the target has moved
            since this SHA.
          examples:
            - c4f0fdfc41adab56630b34f5f4fd4e84a2c5b4d2
          type: string
        source_branch:
          deprecated: true
          description: 'Deprecated: use source_ref. Source branch to merge from.'
          examples:
            - feature/preview
          type: string
        source_is_ephemeral:
          description: Whether source_ref should be resolved from the ephemeral namespace.
          examples:
            - true
          type: boolean
        source_ref:
          description: >-
            Branch or refs/heads ref to merge from. The merge reads the source
            and never updates it. Provide source_ref or the deprecated
            source_branch.
          examples:
            - feature/preview
          type: string
        squash:
          description: >-
            When true, collapse the source into a single new commit whose only
            parent is the current target tip. Defaults to false, which preserves
            the standard merge/fast-forward behavior. Incompatible with the
            ff_only strategy.
          examples:
            - false
          type: boolean
        strategy:
          description: >-
            Merge strategy. merge creates a merge commit when needed, ff_only
            rejects non-fast-forward merges, and ff_prefer fast-forwards when
            possible before falling back to a merge commit.
          enum:
            - merge
            - ff_only
            - ff_prefer
          examples:
            - merge
          type: string
        target_branch:
          description: Destination branch to update. A merge always updates a branch.
          examples:
            - main
          type: string
        target_is_ephemeral:
          description: >-
            Whether target_branch should be resolved from the ephemeral
            namespace.
          type: boolean
      required:
        - target_branch
        - strategy
      type: object
    ReposMergeResponse:
      additionalProperties: false
      description: >-
        Merge outcome including the resulting commit, source and target state,
        merge base information, and retry attempt counters when applicable.
      properties:
        commit_sha:
          description: >-
            Commit SHA for the merge result. For a fast-forward or no-op, this
            is the resulting target tip.
          examples:
            - 41f0d5c6cc5f4d0fb4a3af2de27ccf9a80ab3b84
          type: string
        merge_base_sha:
          description: Merge base SHA when one exists and the backend reports it.
          examples:
            - a2d127e6a4d54bb7390de828a99e36411f0c84df
          type: string
        promoted_commits:
          description: Number of commits promoted from source onto target.
          examples:
            - 3
          format: int32
          minimum: 0
          type: integer
        result:
          description: >-
            Merge outcome: merge_commit, fast_forward, no_op, squash, or
            unknown.
          examples:
            - merged
          type: string
        source:
          $ref: '#/components/schemas/MergeSourceState'
          description: Source ref metadata with branch, ephemeral, and resolved sha.
        target:
          $ref: '#/components/schemas/MergeTargetState'
          description: >-
            Target ref metadata with branch, ephemeral, previous old_sha, and
            resulting new_sha.
        tree_sha:
          description: Tree SHA for the resulting commit or target tip.
          examples:
            - b9532c5d5be50d88e2f45d7c229566b2f1f99731
          type: string
      required:
        - result
        - commit_sha
        - tree_sha
        - source
        - target
        - promoted_commits
      type: object
    ProblemDetails:
      additionalProperties: false
      description: >-
        RFC 9457-compatible problem details payload describing the error
        response.
      properties:
        code:
          description: >-
            A stable, machine-readable error code in snake_case. Branch on
            `code`, not on `detail`. The API description lists the codes.
          type: string
        detail:
          description: >-
            A human-readable explanation specific to this occurrence of the
            problem.
          type: string
        error:
          description: Legacy compatibility field mirroring `detail` for older clients.
          type: string
        instance:
          description: >-
            A URI reference that identifies the specific occurrence of the
            problem.
          type: string
        status:
          description: >-
            The HTTP status code generated by the origin server for this
            occurrence of the problem.
          format: int64
          type: integer
        title:
          description: A short, human-readable summary of the problem type.
          type: string
        type:
          description: >-
            A URI reference that identifies the problem type. `about:blank`
            indicates the generic HTTP status semantics apply.
          type: string
      required:
        - type
        - title
        - status
        - code
      type: object
    MergeConflict:
      additionalProperties: false
      description: >-
        Merge failure caused by a conflict, a moved target branch, or a
        repository change, with the conflicting paths when known.
      properties:
        conflict_paths:
          description: Repository paths that conflicted during the merge.
          items:
            type: string
          type: array
        conflict_type:
          description: >-
            Machine-readable conflict type: merge_conflict, target_moved, or
            repo_changed.
          examples:
            - merge_conflict
          type: string
        error:
          description: High-level conflict result.
          examples:
            - merge conflict
          type: string
        merge_base_sha:
          description: Merge base SHA used when the conflict was calculated.
          type: string
      required:
        - error
      type: object
    GitIdentity:
      additionalProperties: false
      description: Author or committer identity for a commit.
      properties:
        email:
          description: Email address.
          examples:
            - review@example.com
          type: string
        name:
          description: Display name.
          examples:
            - Review Bot
          type: string
      required:
        - name
        - email
      type: object
    MergeSourceState:
      additionalProperties: false
      description: Resolved source ref state for a merge response.
      properties:
        branch:
          deprecated: true
          description: 'Deprecated: use ref. Source branch name.'
          examples:
            - feature/preview
          type: string
        ephemeral:
          description: Whether the source ref was resolved under the ephemeral namespace.
          examples:
            - true
          type: boolean
        ref:
          description: The source ref the merge reads.
          examples:
            - feature/preview
          type: string
        sha:
          description: Resolved source SHA.
          examples:
            - 9eb378bdb5bf1944f6ba0bd5a2c4df3ce32f4df1
          type: string
      required:
        - ref
        - branch
        - ephemeral
        - sha
      type: object
    MergeTargetState:
      additionalProperties: false
      description: >-
        Resolved target ref state for a merge response, including the previous
        and new tip SHAs.
      properties:
        branch:
          description: Target branch name.
          examples:
            - main
          type: string
        ephemeral:
          description: Whether the target ref was resolved under the ephemeral namespace.
          type: boolean
        new_sha:
          description: New target tip SHA after the merge.
          examples:
            - 41f0d5c6cc5f4d0fb4a3af2de27ccf9a80ab3b84
          type: string
        old_sha:
          description: Previous target tip SHA before the merge.
          examples:
            - c4f0fdfc41adab56630b34f5f4fd4e84a2c5b4d2
          type: string
      required:
        - branch
        - ephemeral
        - old_sha
        - new_sha
      type: object
  securitySchemes:
    bearerAuth:
      bearerFormat: JWT
      description: >-
        JWT bearer token signed with your organization's registered signing key.
        There is no OAuth authorization server; you mint tokens yourself and the
        token's `scopes` claim carries the granted permission scopes. Public
        scopes: `git:read` (read repository contents), `git:write` (write
        branches, commits, tags, and notes), `repo:write` (create and manage
        repositories), `org:read` (list an organization's repositories). Each
        operation's security requirement names the scopes it requires. See
        https://code.storage/docs/getting-started/authentication for how to mint
        tokens.
      scheme: bearer
      type: http

````