Posting to plugin's action controller using Ajax + JSON I want to use Ajax to POST to a plugin endpoint and get a JSON response. The plugin I'm using is for Mailchimp newsletter subscriptions and should allow for JSON responses:
https://github.com/aelvan/mailchimp-subscribe-craft
I have my form:
&lt;form action=&quot;&quot; method=&quot;post&quot; novalidate&gt;
  {{ csrfInput() }}
  &lt;input id=&quot;email&quot; name=&quot;email&quot; type=&quot;email&quot; &gt;
  &lt;input type=&quot;submit&quot; value=&quot;Subscribe&quot;&gt;

and my Javascript:
let json = this.toJSONString(this.form);
let xhr = new XMLHttpRequest();
xhr.onload = () =&gt; {
  if (xhr.status &gt;= 200 &amp;&amp; xhr.status &lt; 300) {
    // ...
  } else {
     // ...
  }
};
xhr.open(&quot;POST&quot;, &quot;actions/mailchimp-subscribe/audience/subscribe&quot;, true);
xhr.setRequestHeader(&quot;Content-Type&quot;, &quot;application/json; charset=UTF-8&quot;);
xhr.send(json);

This hits the endpoint, but I get a 404 response:

HTTP 404 – Not Found – yii\web\NotFoundHttpException
Template not found: actions/mailchimp-subscribe/audience/subscribe

As I understand it, I'm correctly posting to the relevent plugin controller action by using the URL actions/mailchimp-subscribe/audience/subscribe. Furthermore, if I do a GET to that URL I get a 400 response which would lead me to believe the routing is correct.
The error therefore seems to be in the Craft controller/routing handler. It's not detecting that I've send a JSON string and that I want a JSON response (and not a template/HTML response).
What's going on here?
In your newsletter form, you should have:

&lt;input type="hidden" name="action" value="mailchimp-subscribe/audience/subscribe"&gt;
&lt;input type="hidden" name="language" value="{{ craft.app.locale.id }}"&gt;


Then, you should POST to '/' + userLocale (where userLocale = $('[name="language"]').val()).

I am using jQuery, and this is working fine:

$.post({
    url: '/' + userLocale,
    dataType: 'json',
    data: $('#form').serialize(),
    success: function(response) {
        console.log(response);
    },
    error: function(response) {
        console.log(response);
    }
});