# "BAD CSRF" when executing PUT using API, curl, and PHP

**URL:** https://meta.discourse.org/t/bad-csrf-when-executing-put-using-api-curl-and-php/153422
**Category:** Development
**Tags:** rest-api
**Created:** [May 31, 2020, 10:31pm UTC](https://meta.discourse.org/t/bad-csrf-when-executing-put-using-api-curl-and-php/153422 "2020-05-31T22:31:46Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![hjalali](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/hjalali/32/181824_2.png) [@hjalali](https://meta.discourse.org/u/hjalali)
#### Post date: [May 31, 2020, 10:31pm UTC](https://meta.discourse.org/t/bad-csrf-when-executing-put-using-api-curl-and-php/153422/1 "2020-05-31T22:31:46Z")

</div>

I have a very simple function that “should” work but it is not for some reason. Can someone help me understand what we are doing wrong.

We keep getting the “BAD CSRF” error.

```
public function changeName()
{
  $url = 'https://www.website.com/{username}.json';
  $data = ['name'=>'James', 'api_key'=>DISCOURSE_API, 'api_username'=>'system'];

  $ch = curl_init($url);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
  curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:multipart/form-data'));
  curl_setopt($ch, CURLOPT_POSTFIELDS,http_build_query($data));

  echo $response = curl_exec($ch);

  if (!$response)
  {
      return false;
  }

}

```

By the way I already tried moving the api\_key and api\_username to the URL above as GET but no difference.

---

<div class="post-metadata">

### Author: ![simon](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/simon/32/339122_2.png) [@simon](https://meta.discourse.org/u/simon)
#### Post date: [May 31, 2020, 11:49pm UTC](https://meta.discourse.org/t/bad-csrf-when-executing-put-using-api-curl-and-php/153422/2 "2020-05-31T23:49:28Z")

</div>

You need to put the `Api-Key` and `Api-Username` values in the request header. There’s a curl example near the end of this topic that could be helpful: [Sync DiscourseConnect user data with the sync\_sso route](https://meta.discourse.org/t/sync-sso-user-data-with-the-sync-sso-route/84398).

---

<div class="post-metadata">

### Author: ![hjalali](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/hjalali/32/181824_2.png) [@hjalali](https://meta.discourse.org/u/hjalali)
#### Post date: [June 1, 2020, 12:16am UTC](https://meta.discourse.org/t/bad-csrf-when-executing-put-using-api-curl-and-php/153422/3 "2020-06-01T00:16:47Z")

</div>

Thanks a lot! That did the trick.

For anyone else with the same problem:

```
$url = 'https://www.website.com/{username}.json';
$data = ['name'=>'George'];
$api_key = CUSTOM_DISCOURSE_API;

$headers = array("Content-Type: multipart/form-data;","Api-Key: $api_key","Api-Username: system",);

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers );
curl_setopt($ch, CURLOPT_POSTFIELDS,http_build_query($data));

$result = curl_exec( $ch );

if ( curl_errno( $ch ) !== 0 ) {
   // Handle error, call curl_close( $ch ) and return.
}

curl_close( $ch );

$discourse_user = json_decode( $result );

```

---

<div class="post-metadata">

### Author: ![hjalali](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/hjalali/32/181824_2.png) [@hjalali](https://meta.discourse.org/u/hjalali)
#### Post date: [June 1, 2020, 12:29am UTC](https://meta.discourse.org/t/bad-csrf-when-executing-put-using-api-curl-and-php/153422/4 "2020-06-01T00:29:27Z")

</div>

Just to add to that, if someone needs to update a “user\_field” replace the $data with this:

```
$data = ['user_fields' => ['1' => 'Something']];

```

The number “1” being the first user\_field I created (as they are assigned by number not name).

---

<div class="post-metadata">

### Author: ![brospars](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/brospars/32/235841_2.png) [@brospars](https://meta.discourse.org/u/brospars)
#### Post date: [October 5, 2021, 9:32am UTC](https://meta.discourse.org/t/bad-csrf-when-executing-put-using-api-curl-and-php/153422/5 "2021-10-05T09:32:26Z")

</div>

Since when it’s mandatory ?  
Didn’t find it in the changelog. I made a tool 2-3 years ago to create categories in batch that worked perfectly fine and now I get this error…

---

<div class="post-metadata">

### Author: ![blake](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/blake/32/157322_2.png) [@blake](https://meta.discourse.org/u/blake)
#### Post date: [October 5, 2021, 3:39pm UTC](https://meta.discourse.org/t/bad-csrf-when-executing-put-using-api-curl-and-php/153422/6 "2021-10-05T15:39:09Z")

</div>

> [@brospars](#):
>
> Since when it’s mandatory ?  
> Didn’t find it in the changelog. I made a tool 2-3 years ago

> [@Discourse REST API Documentation](https://meta.discourse.org/t/discourse-rest-api-documentation/22706/1):
>
> ## ⚠ Deprecation Warning!
> 
> **On April 6th, 2020 we dropped support for all non-HTTP header based authentication (excluding some rss, mail-receiver, and ics routes).** This means that API requests that have an `api_key` and `api_username` in the query params or in the HTTP body of the request will soon stop working.

Sorry about any issues this caused, we did do a slow roll out of this change and notified people the best we could, but its hard to catch every deprecation use.

---

<div class="post-metadata">

### Author: ![JammyDodger](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/jammydodger/32/254611_2.png) [@JammyDodger](https://meta.discourse.org/u/JammyDodger)
#### Post date: [May 4, 2024, 8:05am UTC](https://meta.discourse.org/t/bad-csrf-when-executing-put-using-api-curl-and-php/153422/7 "2024-05-04T08:05:36Z")

</div>


