Skip to content
SunnyWriteUps
Go back

Complete GitHub Migration API Guide

Edit page

Migrating repositories between GitHub accounts, organizations, or platforms can become challenging when dealing with multiple repositories, backups, enterprise compliance, or automated DevOps workflows.

GitHub provides powerful REST APIs for exporting repositories as migration archives. However, developers often face issues with:

This guide covers the complete migration workflow, best practices, troubleshooting, and API usage for both personal and organization repositories.


What is GitHub Migration API?

GitHub Migration APIs allow you to:

GitHub supports:

  1. User migrations
  2. Organization migrations

Official Docs: GitHub Migration APIs Documentation


Types of GitHub Migrations

Migration TypeEndpoint
Personal account repositories/user/migrations
Organization repositories/orgs/{org}/migrations

This distinction is critical.

Many developers accidentally use:

/user/migrations

for organization repositories and receive:

422 Validation Failed

Prerequisites

Before starting migrations, ensure you have:

1. Personal Access Token (PAT)

GitHub migration APIs work best with a Classic PAT.

Create one here:

GitHub Classic Personal Access Token Settings


Required Token Scopes

Personal Repository Migration

Required scopes:

Organization Repository Migration

Required scopes:


Important: SSO Authorization

If your organization uses SAML SSO, your token must be authorized for the organization.

Go to:

GitHub Token Settings

Then:

Without this step, GitHub APIs may return:

Official SSO Docs: GitHub SSO Token Authorization Docs


Personal Repository Migration

Step 1: Start Migration

Example repository:

sunny7899/FastAPI-CRUD

Command:

curl -L -X POST \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-GitHub-Api-Version: 2022-11-28" \
  https://api.github.com/user/migrations \
  --data-raw "{\"lock_repositories\":false,\"repositories\":[\"sunny7899/FastAPI-CRUD\"]}"

Common Git Bash Mistake

Incorrect:

-H
"Authorization: Bearer TOKEN"

This causes:

curl: option -H: requires parameter

Always:


Step 2: Check Migration Status

List migrations:

curl -L \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  https://api.github.com/user/migrations

Response:

[
  {
    "id": 12286999,
    "state": "exported"
  }
]

Important: Migration ID vs Node ID

This is invalid:

LM_kwDOAOdyCc4Au3y2

That is a GraphQL Node ID.

Migration APIs require numeric IDs:

12286999

Step 3: Download Migration Archive

curl -L \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  https://api.github.com/user/migrations/12286999/archive \
  -o fastapi-crud.tar.gz

Extract archive:

tar -xvzf fastapi-crud.tar.gz

Organization Repository Migration

Organization migrations use a completely different endpoint.

Repository example:

angulardevelopment/ssr

Step 1: Create Organization Migration

curl -L -X POST \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "X-GitHub-Api-Version: 2022-11-28" \
  https://api.github.com/orgs/angulardevelopment/migrations \
  --data-raw "{\"lock_repositories\":false,\"repositories\":[\"angulardevelopment/ssr\"]}"

Why /user/migrations Fails for Organization Repositories

Using:

/user/migrations

with organization repositories often returns:

{
  "message": "Validation Failed"
}

because organization repositories must use:

/orgs/{org}/migrations

Step 2: List Organization Migrations

curl -L \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  https://api.github.com/orgs/angulardevelopment/migrations

Step 3: Download Organization Migration Archive

curl -L \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  https://api.github.com/orgs/angulardevelopment/migrations/123456/archive \
  -o ssr-migration.tar.gz

Downloading Archives Using Postman

In Postman:

  1. Create GET request
  2. Add migration archive URL
  3. Add headers
  4. Click dropdown beside Send
  5. Select Send and Download

This downloads the .tar.gz archive directly.


Common Migration Errors & Fixes

1. 404 Not Found

Cause:

Fix:


2. 422 Validation Failed

Cause:

Fix:


3. Problems Parsing JSON

Cause:

Fix: Use:

--data-raw "{\"key\":\"value\"}"

instead of multiline single-quoted JSON.


Best Practices for GitHub Migrations

Use Classic PATs

Migration APIs behave more consistently with classic tokens.


Always Verify Repo Access First

Test:

curl -H "Authorization: Bearer TOKEN" \
https://api.github.com/repos/OWNER/REPO

before starting migrations.


Avoid Repository Locking Unless Necessary

"lock_repositories": false

prevents downtime during exports.


Monitor Migration State

Possible states:

Download archives only when:

"state": "exported"

Security Recommendations

Never:

Use:


Automating GitHub Backups

Migration APIs are excellent for:

You can automate exports using:


Final Thoughts

GitHub Migration APIs are extremely powerful but can be confusing because:

Once configured correctly, the APIs provide a reliable way to automate repository exports, backups, and enterprise migrations.


Useful References


Edit page
Share this post on:

Next Post
Getting Started with Astro and Cloudflare Pages