It seems that this is a common issue. I have googled and searched Stack Exchange about this but didn't find any solution that helps in my situation.

Problem: When trying to use Ajax with admin-ajax.php, I always get the error 400.

POST https://www.example.com/wp-admin/admin-ajax.php 400

This is what I'm trying to achieve:

I'm building a web site for my client with my custom made theme. I created custom post type with custom post status 'Archived'. I'm trying to add a new column with a button in the custom post listing. With this button the admin can set the custom post as archived with single click.

Here is the simplified version of the code. I removed unrelated codes here.

add_action( 'wp_ajax_set_post_archived', 'set_post_archived' );
add_action( 'admin_footer', 'set_post_archived_js' );

function set_post_archived_js() {
    <script type="text/javascript">
        jQuery(document).ready(function($) {

                var data  = {
                    action: 'set_post_archived',
                    post_id: $(this).data('post_id'),   
                    ajaxurl, data,
                    function(response) {
                    alert('Got this from the server: ' + response);

function set_post_archived()
  // The function code here...

The button's code is

<a href="#" data-post_id="70" class="button set-archived-button">Archive</a>

Post id in data-post_id is created dynamically.

As mentioned, this code is on the backend, so wp_ajax_nopriv_{action_hook} shouldn't be required.


I have tried both jQuery.post() and jQuery.ajax(). Seems that, it doesn't make difference. Here is how the code is being loaded if it matters.

In functions.php:

if ( is_admin() ) {
    // Only if on backend
    require get_template_directory() . '/admin/admin-functions.php';

In /admin/admin-functions.php:

global $pagenow;
if ( $pagenow == 'edit.php' || $pagenow == 'post.php' ) {
    require get_template_directory() . '/admin/machines-functions.php';

The actual code with Ajax is in the file /admin/machines-functions.php.

  • 1
    I suspect this is caused by a common mistake, however, this mistake ssimply does not happen if you had used a REST API endpoint for your AJAX rather than the old admin-ajax.php api, and if something had happened it would have given you a plaintext error message in human readable language. Is there a specific reason you decided to use the older API? In fact on closer inspection of your Q I suspect what you want can be done with a request to the WP Core official endpoints that already exist!
    – Tom J Nowell
    Commented Feb 1, 2021 at 16:00
  • No specific reason why I'm using admin-ajax.php. This is all new to me, so I'm learning all this right now and REST API is surely something I will look into in the near future :) Thank you for pointing this out. Commented Feb 1, 2021 at 16:56

1 Answer 1


It seems that you're adding the AJAX action only if $pagenow (the current admin page/file) is edit.php or post.php, and that's not going to work on admin-ajax.php, so you should instead add the action via the admin_init hook if you wish to add the action only on the admin side. E.g.

add_action( 'admin_init', function () {
    add_action( 'wp_ajax_set_post_archived', 'set_post_archived' );
} );
  • 1
    Thank you! This was the solution. It started working partially after removing the use of $pagenow. When I moved all the codes from the different file (machines-functions.php) to main admin functions file (admin-functions.php), it started working perfectly. I believe there is a method to separate these codes in to different file which is being loaded only when the admin is on certain page(s), but I need to look into this more. Commented Feb 1, 2021 at 16:55
  • Well, good luck with that, but do consider using the REST API - it's easy once you get yourself familiar with the fundamental. :)
    – Sally CJ
    Commented Feb 1, 2021 at 17:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.