Ajax return code 400

Here’s a base snippet I use for AJAX submits in WordPress, it might help you out:

<?php
if (isset($_POST['my_theme_ajax_submit']))
    if ( wp_verify_nonce( $_POST['nonce'], 'my_theme_ajax_submit' ) )
        my_theme_ajax_submit(); 

function my_theme_ajax_submit() {
    // do something
    // some php code that fires from AJAX click of #fire
    wp_mail( '[email protected]', 'my_theme_ajax_submit() fired', time());
    wp_die();
}
?>

<button id='fire'>Fire Something</button>

<script>
    jQuery('#fire').click(function(){
        jQuery.ajax({
            type: 'post',
            data: { 
                "my_theme_ajax_submit": "now",
                "nonce" : "<?php echo wp_create_nonce( 'my_theme_ajax_submit' ); ?>"
            },
            success: function(response) { 
                jQuery('#fire').text("Somthing Done!");
            },
            error: function(response) { 
                jQuery('#fire').text("...error!");
            },
        });
    });
</script>

This can be built better – housing the scripts in wp_enque_script(), having the my_theme_ajax_submit() condition check / firing at an early hook like init (instead of within a template), or using the proper wp_ajax_(action) hooks (never seem to work for me) – but it should give an idea.