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

# Repo: Create

> Create a repository. The JWT repo claim supplies the repository name. The optional `repo_name` body field must equal that claim.

A repository starts empty or from a source. `base_repo` is a one-time copy of a Code Storage repository; `upstream` is a lasting link to an external Git host. A copy takes the history of one commit (`base_repo.ref`, or the source HEAD) into one branch, and keeps no link to its source. A sync keeps its upstream, and the repository can sync from it again. Set at most one of the two.

The deprecated form of `base_repo`, with `provider` and `operation`, still works.
#### JWT claims
Required scopes: `repo:write`  
Requires per repo scope: Yes



## OpenAPI

````yaml openapi.json POST /api/repos
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:
    post:
      tags:
        - Repositories
      summary: Create Repo
      description: >-
        Create a repository. The JWT repo claim supplies the repository name.
        The optional `repo_name` body field must equal that claim.


        A repository starts empty or from a source. `base_repo` is a one-time
        copy of a Code Storage repository; `upstream` is a lasting link to an
        external Git host. A copy takes the history of one commit
        (`base_repo.ref`, or the source HEAD) into one branch, and keeps no link
        to its source. A sync keeps its upstream, and the repository can sync
        from it again. Set at most one of the two.


        The deprecated form of `base_repo`, with `provider` and `operation`,
        still works.

        #### JWT claims

        Required scopes: `repo:write`  

        Requires per repo scope: Yes
      operationId: repos-create
      parameters:
        - description: >-
            Optional default branch override. When present, it is used if the
            request body does not already specify one.
          example: main
          in: query
          name: default_branch
          schema:
            type: string
      requestBody:
        content:
          application/json:
            example:
              base_repo:
                auth:
                  token: SOURCE_REPO_READ_TOKEN
                name: pierre/sdk-documentation
                ref: main
              default_branch: feature-preview
              repo_name: pierre/docs-copy
            examples:
              copy:
                description: >-
                  Create an independent repository from one commit of another
                  Code Storage repository.
                summary: Copy
                value:
                  base_repo:
                    auth:
                      token: SOURCE_REPO_READ_TOKEN
                    name: pierre/sdk-documentation
                    ref: main
                  default_branch: feature-preview
                  repo_name: pierre/docs-copy
              empty_repo:
                description: Create a new repository with an explicit default branch.
                summary: Empty repository
                value:
                  default_branch: main
                  repo_name: pierre/my-repo
              generic_git_sync:
                description: >-
                  Mirror a repository from a generic HTTPS Git provider such as
                  GitLab, Bitbucket, Gitea, or Forgejo.
                summary: Generic HTTPS Git sync
                value:
                  default_branch: main
                  repo_name: pierre/repo-name
                  upstream:
                    host: git.example.com
                    name: repo-name
                    owner: org-name
                    provider: gitea
              public_github_sync:
                description: >-
                  Mirror a public GitHub repository without a GitHub App
                  installation.
                summary: Public GitHub sync
                value:
                  default_branch: main
                  repo_name: pierre/hello-world
                  upstream:
                    access: public
                    name: hello-world
                    owner: octocat
                    provider: github
            schema:
              $ref: '#/components/schemas/ReposCreateRequest'
        description: >-
          Create an empty repository, a copy of a Code Storage repository
          (`base_repo`), or a repository that syncs from an external Git host
          (`upstream`).
      responses:
        '200':
          content:
            application/json:
              example:
                http_url: pierre/sdk-documentation
                message: repository created
                repo_id: repo_7f2b3d9
                repo_name: pierre/sdk-documentation
              schema:
                $ref: '#/components/schemas/ReposCreateResponse'
          description: Repository created successfully.
        '400':
          content:
            application/json:
              example:
                code: bad_request
                detail: >-
                  base_repo and upstream cannot both be set. Use base_repo to
                  copy a Code Storage repository, or upstream to sync from an
                  external Git host.
                error: >-
                  base_repo and upstream cannot both be set. Use base_repo to
                  copy a Code Storage repository, or upstream to sync from an
                  external Git host.
                instance: /api/repos
                status: 400
                title: Bad Request
                type: about:blank
              schema:
                $ref: '#/components/schemas/ProblemDetails'
            application/problem+json:
              example:
                code: bad_request
                detail: >-
                  base_repo and upstream cannot both be set. Use base_repo to
                  copy a Code Storage repository, or upstream to sync from an
                  external Git host.
                error: >-
                  base_repo and upstream cannot both be set. Use base_repo to
                  copy a Code Storage repository, or upstream to sync from an
                  external Git host.
                instance: /api/repos
                status: 400
                title: Bad Request
                type: about:blank
              schema:
                $ref: '#/components/schemas/ProblemDetails'
          description: >-
            The repository name was invalid or did not match the JWT repo claim,
            the request set both base_repo and upstream, or the source was
            invalid.
        '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:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
          description: Conflict
        '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:
            - repo:write
components:
  schemas:
    ReposCreateRequest:
      additionalProperties: false
      description: >-
        Create-repository request body. The JWT `repo` claim supplies the
        repository name. The optional `repo_name` field must equal that claim.
        The body also supplies optional default-branch and Git Sync or fork
        configuration.
      properties:
        base_repo:
          $ref: '#/components/schemas/BaseRepo'
          description: >-
            Code Storage repository to copy once. The new repository keeps no
            link to it. Do not set it together with upstream.
        default_branch:
          description: >-
            Default branch for the new repository. Defaults to main when
            omitted.
          examples:
            - main
          type: string
        repo_name:
          description: >-
            Name of the new repository. It can contain a slash. When present, it
            must equal the JWT repo claim. When omitted, the repo claim supplies
            the name.
          examples:
            - pierre/sdk-documentation
          type: string
        upstream:
          $ref: '#/components/schemas/UpstreamConfig'
          description: >-
            External Git host to keep syncing from. The link lasts, and the
            repository can sync again. Do not set it together with base_repo.
      type: object
    ReposCreateResponse:
      additionalProperties: false
      description: >-
        Result of creating a repository, including the assigned internal
        repository ID and the repository URL path.
      properties:
        http_url:
          deprecated: true
          description: 'Deprecated: use repo_name. Repository name or path, not a full URL.'
          examples:
            - pierre/sdk-documentation
          type: string
        message:
          description: High-level creation result.
          examples:
            - repository created
          type: string
        repo_id:
          deprecated: true
          description: 'Deprecated: use repo_name. Stable repository identifier.'
          examples:
            - repo_7f2b3d9
          type: string
        repo_name:
          description: >-
            Repository name or path. It can contain a slash. It matches the JWT
            repo claim.
          examples:
            - pierre/sdk-documentation
          type: string
      required:
        - repo_id
        - repo_name
        - http_url
        - message
      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
    BaseRepo:
      additionalProperties: false
      description: >-
        Code Storage repository that a new repository copies once. The
        deprecated form, with provider and operation, also describes a sync or a
        fork.
      properties:
        auth:
          $ref: '#/components/schemas/BaseRepoAuth'
          description: >-
            Authentication for the source repository. A copy requires
            auth.token.
        default_branch:
          deprecated: true
          description: >-
            Deprecated: use the top-level default_branch for a copy, and
            upstream.branch for a sync.
          type: string
        name:
          description: >-
            Name of the Code Storage repository to copy. In the deprecated form,
            the repository name on the provider.
          examples:
            - templates/starter
          type: string
        operation:
          default: sync
          deprecated: true
          description: >-
            Deprecated: base_repo without provider is a copy, and upstream is a
            sync. In the deprecated form, sync (the default) or fork.
          enum:
            - sync
            - fork
          type: string
        owner:
          deprecated: true
          description: 'Deprecated: omit it for a copy, and use upstream.owner for a sync.'
          type: string
        provider:
          deprecated: true
          description: >-
            Deprecated: omit it for a copy, and use upstream for a sync. In the
            deprecated form, the provider of the source.
          enum:
            - github
            - gitlab
            - bitbucket
            - gitea
            - forgejo
            - codeberg
            - sr.ht
            - sourcehut
            - code.storage
          type: string
        ref:
          description: >-
            Branch, tag, or commit SHA to copy. It defaults to the HEAD of the
            source repository.
          examples:
            - main
          type: string
        sha:
          deprecated: true
          description: 'Deprecated: use ref, which accepts a commit SHA.'
          type: string
        upstream_host:
          deprecated: true
          description: 'Deprecated: use upstream.host.'
          type: string
      required:
        - name
      type: object
    UpstreamConfig:
      additionalProperties: false
      description: External Git host that a new repository keeps syncing from.
      properties:
        access:
          description: >-
            GitHub only. app (the default) reads through the GitHub App
            installation of the organization. public mirrors a public repository
            without an installation, and syncs only on request.
          enum:
            - app
            - public
          type: string
        host:
          description: >-
            Bare hostname of a self-hosted provider, such as gitlab.example.com.
            It defaults to the public host of the provider.
          type: string
        name:
          description: Repository name on the upstream provider.
          examples:
            - hello-world
          type: string
        owner:
          description: Repository owner or namespace on the upstream provider.
          examples:
            - octocat
          type: string
        provider:
          description: External Git host of the upstream repository.
          enum:
            - github
            - gitlab
            - bitbucket
            - gitea
            - forgejo
            - codeberg
            - sr.ht
            - sourcehut
          type: string
      required:
        - provider
        - owner
        - name
      type: object
    BaseRepoAuth:
      additionalProperties: false
      description: >-
        Authentication used to access the base repository for sync or fork
        operations.
      properties:
        auth_type:
          deprecated: true
          description: >-
            Deprecated: use upstream.access for a public GitHub sync. A copy
            needs no auth_type.
          enum:
            - public
            - jwt
          type: string
        token:
          description: JWT with git:read on the source repository. A copy requires it.
          type: string
      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

````