Can't simulate declined transaction in sandbox using Terminal API


I’m trying to test/simulate declined transactions using the Terminal API with a sandbox account. I can’t seem to figure out how to do that. I did read the test values information in and noticed that credit card # 4000000000000002 simulates a declined transaction. However, I don’t think that this applies to Terminal API testing. All I could find was the list of test device ID’s that do various things. Device ID 9fa747a2-25ff-48ee-b078-04381f7c828f is supposed to produce failed payments if the transaction amount is larger that $25. However, I’ve tested with transactions such as $50,000.00 that still resulted in a captured transaction.

Does the list of test device ID’s on that page need to be updated? It seems like it might be out of date. Or maybe I’m doing something wrong?

Any help would be appreciated.

I just wanted to provide some more info for this and hopefully someone at Square will provide some insight. It seems like any checkout transaction up to $50,000.00 works. I receive a total of 6 event notification via webhooks, clearly showing that a payment object was created that shows the transaction is captured.

However, when I try a checkout transaction over $50,000.00, I get only these 3 webhook notifications:

  • terminal.checkout.created with a status of PENDING
  • terminal.checkout.updated with a status of IN_PROGRESS
  • terminal.checkout.updated with a status of CANCELED. This is not an indication of a declined transaction but simply a webhook notification that occurs after the deadline_duration value passes.

I just cannot fathom that my app should simply wait to see if a payment object is created after a certain amount of time. That would not make sense at all. I would assume that a declined payment should result in either another terminal.checkout.updated or a payment.created event with a status value DENIED or something similar. But nothing happens other than the 3 events shown above.

So again, how do I simulate a declined transaction using the Terminal API?! The list of test device IDs in seem to imply that a transaction of $25 using device ID of 9fa747a2-25ff-48ee-b078-04381f7c828f will fail. For me, transactions with values up to $50,000.00 succeed (i.e. captured). But assuming that the documentation is wrong and should state $50,000.00 instead of $25 , my bigger issue is that there is no notification of any kind that the transaction of $50,000.01 or greater failed. I cannot see any additional web hooks that I should subscribe to. I’m subscribed to terminal.checkout.created, terminal.checkout.updated, payment.created, and payment.updated. I don’t see any other events that I should be subscribed to for this particular issue.

Thanks again and sorry for the long-winded message.

Hi @jackgh welcome to the forums!

I’m seeing the same as you for 9fa747a2-25ff-48ee-b078-04381f7c828f, so I think you actually found a bug :slight_smile:. I’ve escalated to the Terminal API team and will follow up once I have more information.

Addressing some of your other concerns: if you’re wanting to know when a payment fails or is declined, you should be looking up the payment object, not the terminal object. The Terminal webhook will technically send a terminal.checkout.updated in this event, I believe, but you won’t be able to tell it was declined from the terminal response without retrieving the payment, so it might be beneficial to listen to payment webhooks as well. The Terminal API will tell you the status of the checkout, not the status of the payment(s). If a card payment is declined, it should create a new payment with the error, but the terminal checkout should still be open technically, so the customer can try with another payment source.

As for the over $50,000…I think that might just be a broad Square error; as far as I know we do not allow merchants to accept over $50,000 for a single transaction, so it might just be auto-canceling since we do not allow it to work in any scenario.

Thanks for the reply @sjosey. Regarding the payment object, I am listening to that eventand hopefully will receive notification when the payment is failed.

Looking forward for an update for the 9fa747a2-25ff-48ee-b078-04381f7c828f device ID. Also, I think the same thing is happening with 22cd266c-6246-4c06-9983-67f0c26346b0.

Hi @sjosey,

Any update on this? I’m not sure if this is something that the API dev team handles and applies to the latest version of the API or if it is something that will be rolled into the next version of the API. I’d appreciate some feedback about how long this might take, if possible.


Hi @jackgh apologies for the delay here. The team is actively tracking this issue but I do not currently have an ETA on when it will be resolved unfortunately. I’ll be sure to update this thread when it is resolved.

This should be resolved now :slight_smile: please let us know if you see otherwise. Thanks for reporting!

Thanks for the update. I do see that the behavior is different now.

Just so that I understand the Terminal API, when a failed card transaction occurs (i.e when done in the sandbox with an amount of greater than $25.00), no payment object is created at all? I’m now seeing:

  • The initial terminal.checkout.created event with status of PENDING
  • The terminal.checkout.updated event with a status of IN_PROGRESS
  • A terminal.checkout.updated event with a status of CANCELED and cancel_reason of TIMED_OUT. This event comes in after the deadline_duration period expires, it seems like.

I’m not sure if this is normal behavior or maybe something is still not right. I thought that a payment object would be created. If you want to review logs, terminal checkout ID fATKhX6CHiqqO is one example.

Thanks again,

Great question, and I was a bit confused on this as well. So, to be clear: if a payment is attempted on the terminal, but fails (ex: got declined), then it should create a payment object with state FAILED, however it will not be attached to the terminal checkout (i.e the payment_id will not be appended to the checkout).

So in the above scenario, this is how it would work: it would be PENDING, IN_PROGRESS (when a payment is being attempted`) and would eventually time out. In the real world, before the time out, a customer could attempt another payment, though. With the failed payments, it should create a payment object (but not attached to the checkout). In the sandbox, no payment object is currently created, though.

I’m guessing you’re implying that a payment object with a failed status is supposed to be created in the sandbox and that it’s just not doing it right now?

With the failed payments, it should create a payment object (but not attached to the checkout). In the sandbox, no payment object is currently created, though.

i was able to (finally) get ahold of a credit card that is “on-hold” and will generate failed transactions. And I tested it in Production and things worked as I was expecting them to. Payment object created and the expected webhooks came in.

So is there a chance that the sandbox would be fixed sometime soon? This is with the test device ID’s 9fa747a2-25ff-48ee-b078-04381f7c828f and 22cd266c-6246-4c06-9983-67f0c26346b0 for transactions > $25. Or is there something that I’m not understanding about the behavior of those test ID’s and that they are now functioning as expected?

I’m sorry to keep pushing with this but it’s really important that I have a clear picture of how the system is supposed to work and that we have a solid testing platform.

Thanks for everything you’ve done.