> ## 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.

# repos.commits.create

> Create a commit by streaming file operations directly to the service. This is designed for automation, AI agents, and other workflows that need atomic Git writes without running a local Git process.

Scope: `git:write` on the repository.



## OpenAPI

````yaml openapi.json POST /api/repos/{repo_name}/commit-pack
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 `400 Bad Request` response for a request body can name the invalid fields
    in `invalid_params`. Each item has the dotted path of the field in `name`,
    for example `deployment.production_branch`, and the rule that the value
    breaks in `reason`.


    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.

    - `ref_guard_failed` (409): a ref guard such as `expected_target_sha` does
    not match the ref; `guard` names it and `current_sha` is the commit of the
    ref.

    - `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): no GitHub App is set up for the
    organization, or the GitHub App of the repository has no usable private key.

    - `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 cluster that serves your
      organisation, such as its cloud location and inbound IP addresses.
    name: Organization
paths:
  /api/repos/{repo_name}/commit-pack:
    post:
      tags:
        - Commits
      summary: Create Commit from Files
      description: >-
        Create a commit by streaming file operations directly to the service.
        This is designed for automation, AI agents, and other workflows that
        need atomic Git writes without running a local Git process.


        Scope: `git:write` on the repository.
      operationId: repos-commits-create
      parameters:
        - description: The repository name, for example `acme/web`.
          example: my-demo-repository
          in: path
          name: repo_name
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/x-ndjson:
            example: >
              {"metadata":{"target_branch":"main","expected_target_sha":"d34db33fd34db33fd34db33fd34db33fd34db33f","commit_message":"Update
              docs","author":{"name":"Docs
              Bot","email":"docs@example.com"},"files":[{"path":"docs/changelog.md","operation":"upsert","content_id":"blob-1","mode":"100644"},{"path":"docs/legacy.txt","operation":"delete","content_id":"blob-2"}]}}

              {"blob_chunk":{"content_id":"blob-1","data":"IyBWZXJzaW9uIDIuMS4wCi0gcmVmcmVzaCBkb2NzCg==","eof":true}}

              {"blob_chunk":{"content_id":"blob-2","data":"","eof":true}}
            schema:
              contentSchema:
                items:
                  additionalProperties: false
                  properties:
                    blob_chunk:
                      $ref: '#/components/schemas/BlobChunk'
                  required:
                    - blob_chunk
                  type: object
                minItems: 1
                prefixItems:
                  - additionalProperties: false
                    properties:
                      metadata:
                        $ref: '#/components/schemas/ReposCommitsCreateRequest'
                    required:
                      - metadata
                    type: object
                type: array
              description: >-
                NDJSON stream. The first line must be `metadata`; subsequent
                lines must be `blob_chunk` payloads. Decoded blob chunks are
                limited to 4 MiB each.
              type: string
        description: >-
          Send newline-delimited JSON where the first line is a `metadata`
          object and each following line is a `blob_chunk`. This lets you stream
          file contents without a local Git client.
        required: true
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommitWriteResponse'
          description: Commit created and written to the target branch.
        '400':
          content:
            application/json:
              example:
                commit: null
                result:
                  message: first payload must be metadata
                  new_sha: ''
                  old_sha: ''
                  status: invalid
                  success: false
                  target_branch: ''
              schema:
                $ref: '#/components/schemas/CommitWriteResponse'
          description: The NDJSON stream was malformed or metadata validation failed.
        '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:
                commit:
                  blob_count: 1
                  commit_sha: 7b3e9f2a1c4d5e6f708192a3b4c5d6e7f8091a2b
                  pack_bytes: 1024
                  target_branch: main
                  tree_sha: e1f2a3b4c5d6e7f8091a2b3c4d5e6f708192a3b4
                result:
                  message: failed to update ref
                  new_sha: 7b3e9f2a1c4d5e6f708192a3b4c5d6e7f8091a2b
                  old_sha: d34db33fd34db33fd34db33fd34db33fd34db33f
                  status: failed
                  success: false
                  target_branch: main
              schema:
                $ref: '#/components/schemas/CommitWriteResponse'
            application/problem+json:
              example:
                type: about:blank
                title: Conflict
                status: 409
                detail: >-
                  base_ref (d34db33fd34db33fd34db33fd34db33fd34db33f) does not
                  match current head c4f0fdfc41adab56630b34f5f4fd4e84a2c5b4d2
                code: ref_guard_failed
                error: >-
                  base_ref (d34db33fd34db33fd34db33fd34db33fd34db33f) does not
                  match current head c4f0fdfc41adab56630b34f5f4fd4e84a2c5b4d2
                guard: expected_target_sha
                current_sha: c4f0fdfc41adab56630b34f5f4fd4e84a2c5b4d2
                commit: null
                result:
                  target_branch: main
                  branch: main
                  old_sha: c4f0fdfc41adab56630b34f5f4fd4e84a2c5b4d2
                  new_sha: ''
                  success: false
                  status: conflict
                  message: >-
                    base_ref (d34db33fd34db33fd34db33fd34db33fd34db33f) does not
                    match current head c4f0fdfc41adab56630b34f5f4fd4e84a2c5b4d2
              schema:
                $ref: '#/components/schemas/CommitWriteRefGuardProblemDetails'
          description: >-
            The branch moved or the requested update could not be applied
            cleanly. When the branch moves after storage writes the commit, the
            body is `application/json`: `result.status` is `failed`, and
            `commit` is the commit that the branch did not get. When
            `expected_target_sha` is not the tip of the branch, the body is
            `application/problem+json` with the code `ref_guard_failed`: `guard`
            names the guard, and `current_sha` is the tip of the branch, which
            `result.old_sha` repeats. The body keeps the members of the failure
            body, and `result.status` is `conflict`.
        '412':
          content:
            application/json:
              example:
                commit: null
                result:
                  message: no changes to commit
                  new_sha: ''
                  old_sha: ''
                  status: precondition_failed
                  success: false
                  target_branch: ''
              schema:
                $ref: '#/components/schemas/CommitWriteResponse'
          description: >-
            The commit makes no changes to the branch: the files match its tip,
            the request has no file operations, or it deletes only paths that do
            not exist. `result.status` is `precondition_failed` and
            `result.message` is `no changes to commit`. A malformed stream, such
            as a file without its final `eof` chunk, also gets `412`, with
            another message. A repository with a GitHub upstream also gets `412`
            when the write cannot reach GitHub: the GitHub App has no usable
            private key, GitHub does not give the App access to the repository,
            or GitHub refuses the push with `401`, `403` or `404`. Then
            `result.status` is `failed` and `result.message` explains the
            failure.
        '413':
          content:
            application/json:
              example:
                commit: null
                result:
                  message: >-
                    commit payload too large: exceeds total blob limit
                    (262144000 bytes)
                  new_sha: ''
                  old_sha: ''
                  status: payload_too_large
                  success: false
                  target_branch: ''
              schema:
                $ref: '#/components/schemas/CommitWriteResponse'
          description: >-
            The decoded file contents of the commit exceeded the total size
            limit.
        '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
        '502':
          content:
            application/json:
              example:
                commit: null
                result:
                  message: >-
                    upstream Git server request failed; the push may or may not
                    have been applied, check the branch before retrying
                  new_sha: ''
                  old_sha: ''
                  status: internal
                  success: false
                  target_branch: ''
              schema:
                $ref: '#/components/schemas/CommitWriteResponse'
          description: >-
            A storage node, the upstream Git server or GitHub failed or could
            not be reached. When the push request to the upstream failed or got
            a server error, the write may have been applied; check the branch
            before retrying. `result.status` is `failed` when GitHub answers the
            push with a server error, and `commit` is the commit that the write
            tried to set. `result.status` is `internal` and `commit` is `null`
            when the push request fails, or when GitHub answers with a server
            error or cannot be reached while the gateway gets its GitHub token.
            `result.message` explains the failure.
        '503':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
          description: Service Unavailable
          headers:
            Retry-After:
              description: Minimum delay in seconds before retrying.
              schema:
                type: string
      security:
        - bearerAuth:
            - git:write
      x-codeSamples:
        - lang: typescript
          label: TypeScript
          source: |-
            import { Pierre } from '@pierre/sdk';

            // The client reads PIERRE_ORG and PIERRE_PRIVATE_KEY.
            const pierre = new Pierre();

            const commit = await pierre.repos.commits.create({
              repo_name: 'my-demo-repository',
              author: { email: 'docs@example.com', name: 'Docs Bot' },
              commit_message: 'Update docs',
              expected_target_sha: 'd34db33fd34db33fd34db33fd34db33fd34db33f',
              target_branch: 'main',
              files: [{ path: 'docs/changelog.md', mode: '100644', content: '# Version 2.1.0\n- refresh docs\n' }, { path: 'docs/legacy.txt', operation: 'delete' }],
            });
            console.log(commit);
        - lang: python
          label: Python
          source: |-
            from pierre import Pierre

            # The client reads PIERRE_ORG and PIERRE_PRIVATE_KEY.
            pierre = Pierre()

            commit = pierre.repos.commits.create(
                repo_name="my-demo-repository",
                author={"email": "docs@example.com", "name": "Docs Bot"},
                commit_message="Update docs",
                expected_target_sha="d34db33fd34db33fd34db33fd34db33fd34db33f",
                target_branch="main",
                files=[{"path": "docs/changelog.md", "mode": "100644", "content": "# Version 2.1.0\n- refresh docs\n"}, {"path": "docs/legacy.txt", "operation": "delete"}],
            )
            print(commit)
        - lang: go
          label: Go
          source: "import (\n\t\"context\"\n\t\"fmt\"\n\t\"strings\"\n\n\tpierre \"github.com/pierrecomputer/sdk/go\"\n)\n\nctx := context.Background()\n// The client reads PIERRE_ORG and PIERRE_PRIVATE_KEY.\nclient, err := pierre.NewClient()\nif err != nil {\n\treturn err\n}\ncommit, err := client.Repos.Commits.Create(ctx, pierre.ReposCommitsCreateParams{\n\tRepoName:          \"my-demo-repository\",\n\tAuthor:            pierre.GitIdentity{Email: \"docs@example.com\", Name: \"Docs Bot\"},\n\tCommitMessage:     \"Update docs\",\n\tExpectedTargetSHA: pierre.String(\"d34db33fd34db33fd34db33fd34db33fd34db33f\"),\n\tTargetBranch:      \"main\",\n\tFiles:             []pierre.CommitFile{{Path: \"docs/changelog.md\", Mode: \"100644\", Content: strings.NewReader(\"# Version 2.1.0\\n- refresh docs\\n\")}, {Path: \"docs/legacy.txt\", Operation: \"delete\"}},\n})\nif err != nil {\n\treturn err\n}\nfmt.Println(commit)"
        - lang: cli
          label: CLI
          source: |-
            pierre repos:commits create \
              --repo-name my-demo-repository \
              --author.email docs@example.com \
              --author.name 'Docs Bot' \
              --commit-message 'Update docs' \
              --expected-target-sha d34db33fd34db33fd34db33fd34db33fd34db33f \
              --target-branch main \
              --file docs/changelog.md \
              --delete docs/legacy.txt
        - lang: bash
          label: cURL
          source: |-
            curl -X POST \
              "https://api.{org}.code.storage/api/repos/my-demo-repository/commit-pack" \
              -H "Authorization: Bearer $PIERRE_TOKEN" \
              -H "Content-Type: application/x-ndjson" \
              --data-binary @- <<'EOF'
              {"metadata":{"author":{"email":"docs@example.com","name":"Docs Bot"},"commit_message":"Update docs","expected_target_sha":"d34db33fd34db33fd34db33fd34db33fd34db33f","files":[{"content_id":"blob-1","mode":"100644","operation":"upsert","path":"docs/changelog.md"},{"content_id":"blob-2","operation":"delete","path":"docs/legacy.txt"}],"target_branch":"main"}}
              {"blob_chunk":{"content_id":"blob-1","data":"IyBWZXJzaW9uIDIuMS4wCi0gcmVmcmVzaCBkb2NzCg==","eof":true}}
              {"blob_chunk":{"content_id":"blob-2","data":"","eof":true}}
            EOF
components:
  schemas:
    CommitWriteResponse:
      additionalProperties: false
      description: >-
        Result of applying an NDJSON commit pack, including the resulting commit
        and branch update.
      properties:
        commit:
          $ref: '#/components/schemas/WrittenCommit'
          description: Commit object information generated by the storage service.
        result:
          $ref: '#/components/schemas/RefUpdateResult'
          description: Final branch update outcome.
      required:
        - commit
        - result
      type: object
    ProblemDetails:
      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
    CommitWriteRefGuardProblemDetails:
      allOf:
        - $ref: '#/components/schemas/RefGuardProblemDetails'
        - properties:
            result:
              $ref: '#/components/schemas/RefUpdateResult'
              description: Final branch update outcome.
          required:
            - result
          type: object
      description: >-
        Problem details of a commit write whose `expected_target_sha` guard
        failed. The body keeps `result`, and `commit` is null.
      type: object
    WrittenCommit:
      additionalProperties: false
      description: Commit object information generated when a pack is applied.
      properties:
        blob_count:
          description: Number of blobs included in the pack.
          format: int32
          minimum: 0
          type: integer
        commit_sha:
          description: SHA of the new commit.
          type: string
        pack_bytes:
          description: Size of the generated pack in bytes.
          format: int64
          minimum: 0
          type: integer
        target_branch:
          description: Branch the commit was written to.
          type: string
        tree_sha:
          description: Tree SHA of the new commit.
          type: string
      required:
        - commit_sha
        - tree_sha
        - target_branch
        - pack_bytes
        - blob_count
      type: object
    RefUpdateResult:
      additionalProperties: false
      description: Branch update outcome for an operation that writes a commit.
      properties:
        branch:
          deprecated: true
          description: 'Deprecated: use target_branch. The branch the operation updates.'
          type: string
        message:
          description: Optional human-readable message.
          type: string
        new_sha:
          description: New tip SHA after the update.
          type: string
        old_sha:
          description: >-
            Previous tip SHA (40-char hex; all zeros when the branch did not
            previously exist).
          type: string
        status:
          description: Status code (ok, conflict, precondition_failed, etc.).
          enum:
            - ok
            - failed
            - precondition_failed
            - conflict
            - not_found
            - unauthorized
            - forbidden
            - timeout
            - invalid
            - payload_too_large
            - unavailable
            - internal
          type: string
        success:
          description: Whether the operation succeeded.
          type: boolean
        target_branch:
          description: The branch the operation updates.
          type: string
      required:
        - target_branch
        - branch
        - old_sha
        - new_sha
        - success
        - status
      type: object
    RefGuardProblemDetails:
      allOf:
        - $ref: '#/components/schemas/ProblemDetails'
        - properties:
            current_sha:
              description: >-
                The commit of the guarded ref when the server checked the guard,
                or 40 zeros when the ref does not exist. Send it as the guard of
                the next attempt. A commit write to a new branch with
                `base_branch` compares the guard with the tip of `base_branch`,
                so `current_sha` is that tip.
              examples:
                - c4f0fdfc41adab56630b34f5f4fd4e84a2c5b4d2
              type: string
            guard:
              description: >-
                The request field of the guard that failed. A request that sends
                a deprecated alias of the field gets the standard name.
              enum:
                - expected_target_sha
                - expected_source_sha
                - expected_notes_ref_sha
              type: string
          required:
            - guard
            - current_sha
          type: object
      description: >-
        Problem details of a failed ref guard, with the code `ref_guard_failed`.
        `guard` names the request field of the guard, and `current_sha` is the
        commit of the guarded ref.
      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

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.