SP-API 403 The security token included in the request is invalid


I’m having trouble with getting order data using the php sdk https://github.com/amazon-php/sp-api-sdk. I’m able to get the access token, but it’s failing when trying to get any data.

use AmazonPHP\SellingPartner\OAuth;
use AmazonPHP\SellingPartner\Regions;
use AmazonPHP\SellingPartner\SellingPartnerSDK;
use Buzz\Client\Curl;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Nyholm\Psr7\Factory\Psr17Factory;
use Psr\Log\NullLogger;

$factory = new Psr17Factory();
$client = new Curl($factory);
$logger = new Logger('BigWallOrderAmazonImport');
$path  = 'amazon.log';
$logger->pushHandler(new StreamHandler($path), Logger::DEBUG);
$httpFactory = new HttpFactory($factory, $factory);
$config = Configuration::forIAMUser(env('LWA_CLIENT_ID'),env('LWA_CLIENT_SECRET'),env('AWS_ACCESS_KEY'),env('AWS_SECRET_KEY'));

$oauth = new OAuth($client, $httpFactory, $config, new NullLogger());

$accessToken = $oauth->exchangeRefreshToken(env('REFRESH_TOKEN'));
$sdk = SellingPartnerSDK::create($client, $factory, $factory, $config, $logger);
$order = $sdk->orders()->getOrder($accessToken, Regions::NORTH_AMERICA, 'order id');

I followed https://developer-docs.amazon.com/sp-api/docs/what-is-the-selling-partner-api and added the seller api role to the iam user. The application is in draft status and I read that, that can sometimes be the problem, but according to the above guide, you don’t have to publish a private app. I’ve self-authorized and am passing the refresh token. I get this error trying whether using sandbox as well as not in sandbox mode.

I’m not sure if I’m missing a step or doing something wrong. Any help would be appreciated.


Have you tested the credentials by using something like Postman to test that they are valid? Also it’s possible that this is an issue with the actual SDK as this isn’t an official Amazon SDK but a 3rd party one.


I hadn’t tested the credentials. I skipped over step 6 on the Creating and configuring IAM policies and entities section of the guide. When going back over those steps and doing step 6 I found three issues.

  1. I mistakenly put the LWA credentials in both the LWA client and AWS variables.

  2. I did not put the inline policy on the user
    In the guide, they have you put the policy on the role, but the SDK suggests adding it to the IAM user. I did not notice that part

  3. Remove setSandbox()
    I haven’t taken a closer look if there is additional setup required to use the sandbox, but I get the access denied while in sandbox mode, but do not with it off. At this time I’m only reading orders, so it’s not a big deal to not be on sandbox.


The sandbox doesn’t need the setSandbox. It’s driven by the URI. However the one annoying part is that the sandbox URI is only for the actual call. Meaning all of the authorization (get access token, assume role, restricted data token) must be requested via the production URI.

Production: sellingpartnerapi-na.amazon.com
Sandbox: sandbox.sellingpartnerapi-na.amazon.com