This is because of security reasons, but Wordpress has prefixes for "unsecure" calls: wp_ajax_nopriv_*.
Both of the hooks need to be defined to work with logged in and anonymous users.
In functions.php define:
add_action( 'wp_ajax_call_stuff', 'my_callback' ); add_action( 'wp_ajax_nopriv_call_stuff', 'my_callback' ); function my_callback() { print_r($_POST); exit; }
Another thing to add is the ajaxurl variable, which is not included on the frontend by default. You can do this in many ways, but I figured the best thing to do is to use wp_localize_script().
wp_localize_script('my_main_script', 'myPrefix', array( 'ajaxurl' => admin_url( 'admin-ajax.php')));
Then, you can call the AJAX request like this:
jQuery.post(myPrefix.ajaxurl, { 'action': 'call_stuff', 'whatever': '1' }, function(response){ alert('The server responded: ' + response); } );