# JSON vs URL Encoded API Calls - JSON returns BAD CSRF

**URL:** https://meta.discourse.org/t/json-vs-url-encoded-api-calls-json-returns-bad-csrf/22406
**Category:** Feature
**Created:** [22 Noviembre, 2014 02:20 UTC](https://meta.discourse.org/t/json-vs-url-encoded-api-calls-json-returns-bad-csrf/22406 "2014-11-22T02:20:09Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![sperok](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sperok/32/114977_2.png) [@sperok](https://meta.discourse.org/u/sperok)
#### Post date: [22 Noviembre, 2014 02:20 UTC](https://meta.discourse.org/t/json-vs-url-encoded-api-calls-json-returns-bad-csrf/22406/1 "2014-11-22T02:20:09Z")

</div>

Is there possibly a difference in the handling of JSON and formencoded data by the REST API?

If I create a topic it works with Content-Type: application/x-www-formencoded:

```
POST /posts HTTP/1.1
Content-Type: application/x-www-form-urlencoded

api_key=8d3ca248f3eREMOVEDREMOVEDREMOVEDREMOVEDREMOVED868abd4f&api_username=spero&raw=http://www.youtube.com/watch?v=05zrCwLDkVQ&title=What's Good About Compassion&is_warning=false&category=33&archetype=regular

```

but not for JSON, returning 403 Forbidden BAD CSRF which makes me think the api key and username are not being pulled from the JSON data the same way they are from the form encoded above. Or did I screw up something in the JSON? Changing the URL to end in .json has no impact.

```
POST /posts HTTP/1.1
Content-Type: application/json

{ "api_key":"8d3ca248f3eREMOVEDREMOVEDREMOVEDREMOVED868abd4f", "api_username":"spero", "raw":"http://www.youtube.com/watch?v=05zrCwLDkVQ", "title":"What's Good About Compassion", "is_warning":"false", "category":"33", "archetype":"regular" } 

```

My guess is that as soon as I hit enter whatever silly mistake I made jumps off the page.

---

<div class="post-metadata">

### Author: ![riking](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/riking/32/170938_2.png) [@riking](https://meta.discourse.org/u/riking)
#### Post date: [22 Noviembre, 2014 08:05 UTC](https://meta.discourse.org/t/json-vs-url-encoded-api-calls-json-returns-bad-csrf/22406/2 "2014-11-22T08:05:41Z")

</div>

Hm, it’s possible Rails doesn’t parse the json as form parameters. What language are you in where form parameters are hard to do?

---

<div class="post-metadata">

### Author: ![Mittineague](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mittineague/32/114259_2.png) [@Mittineague](https://meta.discourse.org/u/Mittineague)
#### Post date: [22 Noviembre, 2014 08:15 UTC](https://meta.discourse.org/t/json-vs-url-encoded-api-calls-json-returns-bad-csrf/22406/3 "2014-11-22T08:15:19Z")

</div>

Forms send inputs as Strings, but shouldn’t “category” be an Int?

---

<div class="post-metadata">

### Author: ![sperok](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sperok/32/114977_2.png) [@sperok](https://meta.discourse.org/u/sperok)
#### Post date: [22 Noviembre, 2014 19:58 UTC](https://meta.discourse.org/t/json-vs-url-encoded-api-calls-json-returns-bad-csrf/22406/4 "2014-11-22T19:58:58Z")

</div>

I was just prototyping using curl and a REST test tool before starting to code when I found this. It is obviously not a big deal to form encode, but wondering if this may be a generic defect in using the REST APIs with JSON data.

Nice catch on the int vs string @Mittineague, but removing the quotes around the category value does not have an impact on the 403 Forbidden error. If the BAD CSRF problem does get fixed it might then come into play.

Based on the example below, this may have worked at some point in time. It is failing with a fresh upgrade to 1.2.0.beta2.

> [@trident](#):
>
> While not very well documented, it is covered in the wp-discourse code.
> 
> Here’s an example in ruby (from some older stuff I was working on):
> 
> require ‘httparty’  
> @result = HTTParty.post(“\<Discourse URL\>/posts”,  
> :body =\> { :api\_key =\> [‘discourse\_api\_key’], # Global API Key.  
> :api\_username =\> [‘discourse\_api\_username’], # Username to post as.  
> :title =\> [“title”], # Title of topic.  
> :raw =\> “\<contents as string\>”,  
> :category =\> [‘discourse\_api\_category’], #Category to post to.  
> :skip\_validations =\> ‘true’, #Ignores min post length, min title length… etc  
> :auto\_track =\> [‘discourse\_auto\_track’] # User posted as will track the topic.  
> }.to\_json,  
> :headers =\> { ‘Content-Type’ =\> ‘application/json’ } );

---

<div class="post-metadata">

### Author: ![trident](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/trident/32/2078_2.png) [@trident](https://meta.discourse.org/u/trident)
#### Post date: [22 Noviembre, 2014 20:30 UTC](https://meta.discourse.org/t/json-vs-url-encoded-api-calls-json-returns-bad-csrf/22406/5 "2014-11-22T20:30:18Z")

</div>

Wow, that’s from the past! I believe there were some issues in the past where a CSRF would bubble up even if that wasn’t the main cause of the error. You may need to still use `skip_validations` while posting short messages (as you may be hitting the min post length or other checks.) Otherwise, I believe that content posting should be done via json encoded data.

---

<div class="post-metadata">

### Author: ![sperok](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sperok/32/114977_2.png) [@sperok](https://meta.discourse.org/u/sperok)
#### Post date: [22 Noviembre, 2014 20:44 UTC](https://meta.discourse.org/t/json-vs-url-encoded-api-calls-json-returns-bad-csrf/22406/6 "2014-11-22T20:44:14Z")

</div>

No change with skip\_validations: true added to the JSON and category properly coded as an integer. And I would have thunk that behavior would be consistent for JSON or form-encoded. Now this is a mission …

```
POST /posts HTTP/1.1
Content-Type: application/json

{ "api_key":"8d3ca248f3e30e5985a11344568b4ec52a599533f46878bea96f5c5d868abd4f", "api_username":"spero", "raw":"http://www.youtube.com/watch?v=05zrCwLDkVQ", "title":"What's Good About Compassion", "skip_validations": true, "is_warning":false, "category":33, "archetype":"regular" }

```

---

<div class="post-metadata">

### Author: ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### Post date: [23 Noviembre, 2014 07:25 UTC](https://meta.discourse.org/t/json-vs-url-encoded-api-calls-json-returns-bad-csrf/22406/7 "2014-11-23T07:25:40Z")

</div>

I need to patch rails to get rid of that warning its a pain in the behind

---

<div class="post-metadata">

### Author: ![jesselperry](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/jesselperry/32/119501_2.png) [@jesselperry](https://meta.discourse.org/u/jesselperry)
#### Post date: [16 Enero, 2016 23:22 UTC](https://meta.discourse.org/t/json-vs-url-encoded-api-calls-json-returns-bad-csrf/22406/8 "2016-01-16T23:22:58Z")

</div>

Sorry to revive an old topic, but I think this would be helpful to note for future searchers. I didn’t find this information elsewhere.

I was running into this same error when POSTing with JSON data, but I fixed it by just adding the api\_key and api\_usernames to the URL that’s called.

---

<div class="post-metadata">

### Author: ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### Post date: [31 Marzo, 2016 06:53 UTC](https://meta.discourse.org/t/json-vs-url-encoded-api-calls-json-returns-bad-csrf/22406/9 "2016-03-31T06:53:07Z")

</div>

This is not really a bug, it is a feature request, can be achieved with middleware, not built in to Rails.

Not supporting `Content-Type: application/json` does make it slightly more annoying to consume the API via curl and other trivial tools. I am open to adding support for this.

---

<div class="post-metadata">

### Author: ![chapoi](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/chapoi/32/537252_2.png) [@chapoi](https://meta.discourse.org/u/chapoi)
#### Post date: [4 Diciembre, 2025 11:33 UTC](https://meta.discourse.org/t/json-vs-url-encoded-api-calls-json-returns-bad-csrf/22406/10 "2025-12-04T11:33:23Z")

</div>


