Skip to content

Instantly share code, notes, and snippets.

@jonmagic
Last active March 27, 2024 17:34
Show Gist options
  • Star 97 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
  • Save jonmagic/5282384165e0f86ef105 to your computer and use it in GitHub Desktop.
Save jonmagic/5282384165e0f86ef105 to your computer and use it in GitHub Desktop.
Complete issue import API walkthrough with curl

This gist describes a new GitHub API for importing issues. This API hasn't been finalized yet, but when it is -- it will be announced on the official API blog.

Overview:

General notes

To access the Issue Import API, you'll need to include application/vnd.github.golden-comet-preview in your request's Accept header. You'll also need to have admin permissions on the repository.

The maximum request size is 1MB.

Issues and comments created with this API do not trigger any notifications to mentioned users or users watching the repository into which issues are being imported. This is unlike the Issues API which does trigger notifications).

Like all other API requests, requests made to the Issue Import API are affected by regular API rate limits and abuse rate limits.

Issue imports started with this API are processed in the background asynchronously. When you start an import, you get back an import URL which you can use to check if the import completed, and whether it completed successfully or not. Because of this background processing, issue numbers are handed out to successfully imported issues once the processing is completed, and not when you start an import. As a result, if you use this API to submit two imports for issues A and B, and B is submitted after A, but before A's import completes, then it is possible that B will have a lower issue number than A. If you need to make sure that issues have specific numbers, then the recommended approach is that you start an import, wait for that import to complete and make sure it completed successfully, and only after that start a new import.

If you have any feedback or questions about the Issue Import API, please get in touch.

Create a repository

Create a repository using the web interface or the API.

Here is an example API request to create a repository:

curl -X POST -H "Authorization: token ${GITHUB_TOKEN}" \
  -d '{"name":"foo","private":true}' \
  https://api.github.com/user/repos

Try to start an issue import with incomplete data

The Issue Import API attempts to provide actionable feedback when a request does not meet validation criteria.

Request

curl -X POST -H "Authorization: token ${GITHUB_TOKEN}" \
  -H "Accept: application/vnd.github.golden-comet-preview+json" \
  -d '{"issue":{"title":"My money, mo issues"}}' \
  https://api.github.com/repos/${GITHUB_USERNAME}/foo/import/issues

Response

{
  "message": "Validation Failed",
  "errors": [
    {
      "resource": "Issue",
      "code": "missing_field",
      "field": "body"
    }
  ],
  "documentation_url": "https://developer.github.com/v3"
}

Start an issue import

Just make a post request to the import issues API endpoint for the repository and include the issue and comments json as data. An issue only requires the following fields:

{
  "issue": {
    "title": "Imported from some other system",
    "body": "..."
  }
}

And an issue with a comment only needs the comment body added:

{
  "issue": {
    "title": "Imported from some other system",
    "body": "..."
  },
  "comments": [
    {
      "body": "talk talk"
    }
  ]
}

Request

curl -X POST -H "Authorization: token ${GITHUB_TOKEN}" \
  -H "Accept: application/vnd.github.golden-comet-preview+json" \
  -d '{"issue":{"title":"Fix broken widgets","body":"- [ ] widget 1\n- [ ] widget 2","created_at":"2014-03-16T18:21:16Z"},"comments":[{"body":"Can we wrap this up soon?","created_at":"2014-03-16T17:15:42Z"}]}' \
  https://api.github.com/repos/${GITHUB_USERNAME}/foo/import/issues

Response

{
  "id": 3,
  "status": "pending",
  "url": "https://api.github.com/repos/jonmagic/foo/import/issues/3",
  "import_issues_url": "https://api.github.com/repos/jonmagic/foo/import/issues",
  "repository_url": "https://api.github.com/repos/jonmagic/foo"
}

Supported issue and comment fields

The complete json schema looks like this:

{
  "issue": {
    "title": "Imported from some other system",
    "body": "...",
    "created_at": "2014-01-01T12:34:58Z",
    "closed_at": "2014-01-02T12:24:56Z",
    "updated_at": "2014-01-03T11:34:53Z",
    "assignee": "jonmagic",
    "milestone": 1,
    "closed": true,
    "labels": [
      "bug",
      "low"
    ]
  },
  "comments": [
    {
      "created_at": "2014-01-02T12:34:56Z",
      "body": "talk talk"
    }
  ]
}

Note: The body of an issue or comment will be parsed and rendered using Markdown if the created_at value is set to a time after 2009-04-20T19:00:00Z, and using Textile if it's older. The body may be at most 65535 characters long. As of 2016-03-15 all newly created issues will be rendered with Markdown regardless of the created_at timestamp date.

Check status of issue import

After making the API request to import an issue you can check the status of the import by making a get request to the url value from the response in the previous post request.

Request

curl -H "Authorization: token ${GITHUB_TOKEN}" \
  -H "Accept: application/vnd.github.golden-comet-preview+json" \
  https://api.github.com/repos/#{GITHUB_USERNAME}/foo/import/issues/3

Response

{
  "id": 3,
  "status": "imported",
  "url": "https://api.github.com/repos/jonmagic/foo/import/issues/3",
  "import_issues_url": "https://api.github.com/repos/jonmagic/foo/import/issues",
  "repository_url": "https://api.github.com/repos/jonmagic/foo",
  "issue_url": "https://api.github.com/repos/jonmagic/foo/issues/1"
}

Check status of multiple issues

You can check the status of issues imported since a date or date and time.

Request

curl -H "Authorization: token ${GITHUB_TOKEN}" \
  -H "Accept: application/vnd.github.golden-comet-preview+json" \
  https://api.github.com/repos/#{GITHUB_USERNAME}/foo/import/issues?since=2015-03-15

Response

[
  {
    "id": 3,
    "status": "imported",
    "url": "https://api.github.com/repos/jonmagic/foo/import/issues/3",
    "import_issues_url": "https://api.github.com/repos/jonmagic/foo/import/issues",
    "repository_url": "https://api.github.com/repos/jonmagic/foo",
    "issue_url": "https://api.github.com/repos/jonmagic/foo/issues/1"
  }
]

Import fails because issue has an invalid milestone, assignee, creator or label

What happens if you try to import an issue with an invalid attributes?

Import issue request

curl -X POST -H "Authorization: token ${GITHUB_TOKEN}" \
  -H "Accept: application/vnd.github.golden-comet-preview+json" \
  -d '{"issue":{"title":"Fix broken widgets","body":"...","milestone":5,
      "assignee":"bobbyfoobar","labels":["bug","invalid,label"]}}' \
  https://api.github.com/repos/${GITHUB_USERNAME}/foo/import/issues

Import issue response

{
  "id": 7,
  "status": "pending",
  "url": "https://api.github.com/repos/jonmagic/foo/import/issues/7",
  "import_issues_url": "https://api.github.com/repos/jonmagic/foo/import/issues",
  "repository_url": "https://api.github.com/repos/jonmagic/foo"
}

Import status request

curl -H "Authorization: token ${GITHUB_TOKEN}" \
  -H "Accept: application/vnd.github.golden-comet-preview+json" \
  https://api.github.com/repos/#{GITHUB_USERNAME}/foo/import/issues/7

Import status response

{
  "id": 7,
  "status": "failed",
  "url": "https://api.github.com/repos/jonmagic/foo/import/issues/7",
  "import_issues_url": "https://api.github.com/repos/jonmagic/foo/import/issues",
  "repository_url": "https://api.github.com/repos/jonmagic/foo",
  "created_at": "2015-03-18T19:40:53-07:00",
  "updated_at": "2015-03-18T19:40:58-07:00",
  "errors": [
    {
      "location": "/issue/milestone",
      "resource": "Issue",
      "field": "milestone",
      "value": "5",
      "code": "invalid"
    },
    {
      "location": "/issue/assignee",
      "resource": "Issue",
      "field": "assignee",
      "value": "bobbyfoobar",
      "code": "invalid"
    },
    {
      "location": "/issue/labels[1]",
      "resource": "Label",
      "field": "name",
      "value": "invalid,label",
      "code": "invalid"
    }
  ]
}

Import fails because of unexpected comment creation error

Import issue request

curl -X POST -H "Authorization: token ${GITHUB_TOKEN}" \
  -H "Accept: application/vnd.github.golden-comet-preview+json" \
  -d '{"issue":{"title":"foo","body":"1"},"comments":[{"body":"fail this comment somehow"}]}' \
  https://api.github.com/repos/${GITHUB_USERNAME}/foo/import/issues

Import issue response

{
  "id": 12,
  "status": "pending",
  "url": "https://api.github.com/repos/jonmagic/foo/import/issues/12",
  "import_issues_url": "https://api.github.com/repos/jonmagic/foo/import/issues",
  "repository_url": "https://api.github.com/repos/jonmagic/foo",
  "created_at": "2015-03-18T21:45:58-07:00",
}

Import status request

curl -H "Authorization: token ${GITHUB_TOKEN}" \
  -H "Accept: application/vnd.github.golden-comet-preview+json" \
  https://api.github.com/repos/#{GITHUB_USERNAME}/foo/import/issues/12

Import status response

{
  "id": 12,
  "status": "failed",
  "url": "https://api.github.com/repos/jonmagic/foo/import/issues/12",
  "import_issues_url": "https://api.github.com/repos/jonmagic/foo/import/issues",
  "repository_url": "https://api.github.com/repos/jonmagic/foo",
  "created_at": "2015-03-18T21:45:58-07:00",
  "updated_at": "2015-03-18T21:46:05-07:00",
  "issue_url": "https://api.github.com/repos/jonmagic/foo/issues/7",
  "errors": [
    {
      "location": "/comments[0]",
      "resource": "IssueComment",
      "field": null,
      "value": null,
      "code": "error"
    }
  ]
}
@mpdude
Copy link

mpdude commented Feb 4, 2023

💚 to Jonathan for the above statement and 👍 to Steffen for the suggestion.

It's interesting to see that there is an API variant still being exposed (and functional as of today) that allows some more freedom over the date etc. of issues created, with apparently no team and responsibility assigned to it.

@burner
Copy link

burner commented Oct 15, 2023

I have been trying to use this on an organization, after successfully testing this api on a repo created by my test user.

It fails with the result

{"documentation_url":"https:\/\/docs.github.com\/rest","message":"Not Found"}

I don't know how to figure this one out, I triple checked the org and repo name, but no success.

Does anybody have any idea?

@AARP41298
Copy link

@burner do you solve it?
i thought that github-csv-tools was broken, but with the curl example above and Thunder Client i get the same error

@burner
Copy link

burner commented Oct 27, 2023

I re-tried a few days later and it worked. I don't know why. Result can be seen here https://github.com/dlang/visuald/issues

@AARP41298
Copy link

Thanks. I solve it using the GitHub CLI command of
https://docs.github.com/en/rest/issues/issues?apiVersion=2022-11-28#create-an-issue

Maybe curl request for new tokens are disable the first 24hr?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment