# How to create course using API?

**URL:** <https://discuss.openedx.org/t/how-to-create-course-using-api/8471>\
**Category:** Development\
**Tags:** how-to\
**Created:** [October 11, 2022, 5:58am UTC](https://discuss.openedx.org/t/how-to-create-course-using-api/8471 "2022-10-11T05:58:22Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![bhumi](https://avatars.discourse-cdn.com/v4/letter/b/edb3f5/32.png) [@bhumi](https://discuss.openedx.org/u/bhumi)\
**Post date:** [October 11, 2022, 5:58am UTC](https://discuss.openedx.org/t/how-to-create-course-using-api/8471/1 "2022-10-11T05:58:22Z")

</div>

I have redered /api-docs but seems there is no api for creating course. How can I create course using API via postman?

---

<div class="post-metadata">

**Author:** ![braden](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/braden/32/46_2.png) [@braden](https://discuss.openedx.org/u/braden)\
**Post date:** [October 12, 2022, 10:46pm UTC](https://discuss.openedx.org/t/how-to-create-course-using-api/8471/2 "2022-10-12T22:46:50Z")

</div>

Hi @bhumi,

There is a simple technique you can use to answer such questions:

1. Go to the Studio home page and click “New Course”
2. Right-click anywhere on the page and click “Inspect” or the equivalent in your browser
3. Go to the “Network” tab. Clear any entries currently there and enable “Preserve Log”
4. Fill out the New Course form and hit Create.
5. Check the Network log to see the request:

```auto
POST /course/
{org: "OpenCraftX", number: "TEST", display_name: "A Test Course", run: "101"}

```

^ That is the API you can use to create a course.

---

<div class="post-metadata">

**Author:** ![bhumi](https://avatars.discourse-cdn.com/v4/letter/b/edb3f5/32.png) [@bhumi](https://discuss.openedx.org/u/bhumi)\
**Post date:** [October 13, 2022, 4:57am UTC](https://discuss.openedx.org/t/how-to-create-course-using-api/8471/3 "2022-10-13T04:57:00Z")

</div>

@braden Api is giving me “CSRF verification failed. Request aborted.” error while calling from postman

---

<div class="post-metadata">

**Author:** ![bhumi](https://avatars.discourse-cdn.com/v4/letter/b/edb3f5/32.png) [@bhumi](https://discuss.openedx.org/u/bhumi)\
**Post date:** [October 13, 2022, 6:26am UTC](https://discuss.openedx.org/t/how-to-create-course-using-api/8471/4 "2022-10-13T06:26:35Z")

</div>

I have passed X-CSRFToken:{{csrftoken}} in header and this line in tests section of postman

var xsrfCookie = postman.getResponseCookie(“csrftoken”); postman.setEnvironmentVariable(‘csrftoken’, xsrfCookie.value);

still getting same error

---

<div class="post-metadata">

**Author:** ![braden](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/braden/32/46_2.png) [@braden](https://discuss.openedx.org/u/braden)\
**Post date:** [October 14, 2022, 1:39am UTC](https://discuss.openedx.org/t/how-to-create-course-using-api/8471/5 "2022-10-14T01:39:52Z")

</div>

Did you generate the CSRF token using the same credentials (e.g. OAuth bearer token or JWT) that you’re using to authenticate the request? Try using the `/csrf/api/v1/token` API endpoint to retrieve the CSRF token, then submit it with `X-CSRFToken`.

---

<div class="post-metadata">

**Author:** ![bhumi](https://avatars.discourse-cdn.com/v4/letter/b/edb3f5/32.png) [@bhumi](https://discuss.openedx.org/u/bhumi)\
**Post date:** [October 14, 2022, 5:59am UTC](https://discuss.openedx.org/t/how-to-create-course-using-api/8471/6 "2022-10-14T05:59:33Z")

</div>

I have taken csrf toekn from browser cookie. I have called csrf/api/v1/token and it’s returning token but still getting 403 error

I have called

/csrf/api/v1/token without any payload and it’s returning

{  
“csrfToken”: “”  
}

I am passing this token in /couse api header like

X-CSRFToken:

but getting same error

---

<div class="post-metadata">

**Author:** ![bhumi](https://avatars.discourse-cdn.com/v4/letter/b/edb3f5/32.png) [@bhumi](https://discuss.openedx.org/u/bhumi)\
**Post date:** [October 14, 2022, 2:39pm UTC](https://discuss.openedx.org/t/how-to-create-course-using-api/8471/7 "2022-10-14T14:39:22Z")

</div>

@braden I have tried calling api using csrftoken from cookie and /course api is giving 200 status code but it’s not creating course inside the openedx

---

<div class="post-metadata">

**Author:** ![braden](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/braden/32/46_2.png) [@braden](https://discuss.openedx.org/u/braden)\
**Post date:** [October 14, 2022, 5:05pm UTC](https://discuss.openedx.org/t/how-to-create-course-using-api/8471/8 "2022-10-14T17:05:04Z")

</div>

Are you checking for the course using the same user that created the course? What happens if you try creating the exact same course twice?

Basically, I suspect that it’s working but you’re not seeing the course due to permissions or something.

---

<div class="post-metadata">

**Author:** ![bhumi](https://avatars.discourse-cdn.com/v4/letter/b/edb3f5/32.png) [@bhumi](https://discuss.openedx.org/u/bhumi)\
**Post date:** [October 17, 2022, 3:31pm UTC](https://discuss.openedx.org/t/how-to-create-course-using-api/8471/9 "2022-10-17T15:31:38Z")

</div>

I am getting 200 status only so not getting if it is creating course or not. How can I fix the issue? Which permission I need to set? Also, response is html content. It’s not giving created course id

---

<div class="post-metadata">

**Author:** ![braden](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/braden/32/46_2.png) [@braden](https://discuss.openedx.org/u/braden)\
**Post date:** [October 17, 2022, 8:35pm UTC](https://discuss.openedx.org/t/how-to-create-course-using-api/8471/10 "2022-10-17T20:35:59Z")

</div>

Are you setting the `Accept: application/json` header? Because that is required. This endpoint is shared by both HTML and JSON responses. See [the code here for details](https://github.com/openedx/edx-platform/blob/master/cms/djangoapps/contentstore/views/course.py#L279-L280).

---

<div class="post-metadata">

**Author:** ![bhumi](https://avatars.discourse-cdn.com/v4/letter/b/edb3f5/32.png) [@bhumi](https://discuss.openedx.org/u/bhumi)\
**Post date:** [October 18, 2022, 4:38am UTC](https://discuss.openedx.org/t/how-to-create-course-using-api/8471/11 "2022-10-18T04:38:51Z")

</div>

Yes, I have set application/json in content-type header

---

<div class="post-metadata">

**Author:** ![Shabeer\_Khan](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/shabeer_khan/32/5101_2.png) [@Shabeer\_Khan](https://discuss.openedx.org/u/Shabeer_Khan)\
**Post date:** [March 29, 2023, 9:09am UTC](https://discuss.openedx.org/t/how-to-create-course-using-api/8471/12 "2023-03-29T09:09:12Z")

</div>

Hi @bhumi ,

Did you find the solution, I am facing the same issue in postman.  
CSRF verification failed. Request aborted.  
can you please share the solution.

---

<div class="post-metadata">

**Author:** ![Daniyal\_Farman](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/daniyal_farman/32/5078_2.png) [@Daniyal\_Farman](https://discuss.openedx.org/u/Daniyal_Farman)\
**Post date:** [May 22, 2023, 9:09am UTC](https://discuss.openedx.org/t/how-to-create-course-using-api/8471/13 "2023-05-22T09:09:10Z")

</div>

I got this api and I tried this in postman  
First I was getting csrf token failed  
Then I hit csrf api and got csrf token and added in the header section with X-CSRFToken and it’s value  
Now getting url not found

---

<div class="post-metadata">

**Author:** ![Daniyal\_Farman](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/daniyal_farman/32/5078_2.png) [@Daniyal\_Farman](https://discuss.openedx.org/u/Daniyal_Farman)\
**Post date:** [May 22, 2023, 11:36am UTC](https://discuss.openedx.org/t/how-to-create-course-using-api/8471/14 "2023-05-22T11:36:35Z")

</div>

Issue has been resolved you can use another openedx studio api api/v1/course\_runs/  
It will create course for you in studio. All you have to pass authentication access token in oauth2.0

---

<div class="post-metadata">

**Author:** ![Ian\_Campbell](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/ian_campbell/32/5375_2.png) [@Ian\_Campbell](https://discuss.openedx.org/u/Ian_Campbell)\
**Post date:** [June 10, 2023, 7:41am UTC](https://discuss.openedx.org/t/how-to-create-course-using-api/8471/15 "2023-06-10T07:41:10Z")

</div>

I’m trying to hit the api/v1/course\_runs/ endpoint mentioned by [Daniyal\_Farman]

I can generate a token using the csrf/api/v1/token but when I try to use it in Postman I get  
“detail”: “Authentication credentials were not provided.”

Any clarification would be appreciated.

---

<div class="post-metadata">

**Author:** ![SeifHafri](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/seifhafri/32/4432_2.png) [@SeifHafri](https://discuss.openedx.org/u/SeifHafri)\
**Post date:** [September 6, 2023, 2:57pm UTC](https://discuss.openedx.org/t/how-to-create-course-using-api/8471/16 "2023-09-06T14:57:17Z")

</div>

Any solution ? I am facing the same problem

---

<div class="post-metadata">

**Author:** ![AntonOfTheWoods](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/antonofthewoods/32/301_2.png) [@AntonOfTheWoods](https://discuss.openedx.org/u/AntonOfTheWoods)\
**Post date:** [October 21, 2025, 2:16pm UTC](https://discuss.openedx.org/t/how-to-create-course-using-api/8471/17 "2025-10-21T14:16:42Z")

</div>

Ok, I just spent several HOURS trying to get this to work and, alas, it bested me. The problem is that you need to get a session from the LMS, then send the session and get a token from the LMS, then login to the LMS, then somehow send cookies that you got (or some of them???) to the CMS to get ANOTHER token - and btw you get a cookie `csrftoken` which is DIFFERENT to what you get back from the `token` endpoint - then POST all of that to the CMS `course` (including all the cookies and the second x-csrftoken).

It definitely works if you copy the cURL from chrome but I was unfortuntely unable to get it to work with self-constructed curls. I guess that means I have a PR to do…

It also looks like [the documentation](https://docs.openedx.org/projects/edx-platform/en/latest/references/auth_code_samples.html) is no longer up-to-date here, as the following returns HTTP 400 with `{"error": "unsupported_grant_type"}`:

```bash
curl -v -X POST -d '{"client_id": "login-service-client-id", "grant_type": "password", "username": "myusername", "password": "mypasswor", "token_type": "JWT"}' https://training.openedx.io/oauth2/access_token

```

UPDATE: There is, I now see, `./manage.py cms create_course --help`, which isn’t quite a nice as a proper API, but it’ll do in a pinch!
