Terminal checkouts changing to IN_PROGRESS after being COMPLETED

as title says, recently I have noticed my terminal checkouts changing to IN_PROGRESS a few minutes after being completed. So after the customer has left because the payment was complete, I have noticed them changing to IN_PROGRESS. this is making my POS say that the orders are unpaid?

why is this happening? How long do they stay in progress? and is there something wrong? will these transactions fail or time out.

EDIT: ok so it seems the webhooks are being sent out of order. The in progress webhook triggered and then the completed one triggered 7 seconds later. But the completed webhook was sent first. SO it is a problem with your system not keeping track of a queue i guess. When will this be fixed? Or should I be checking my code and if already set to completed do not update to in_progress?

:wave: With Square webhooks as outlined in the Requirements and Limitations there is no guarantee of the delivery order. We do our best to send events as they happen however from time to time they do get out of order. :slightly_smiling_face:

So do you recommend not updating the payment status if it is already set to COMPLETED. or can it change to something else?

I’m not sure I fully understand the question. The IN_PROGRESS event was generated and sent before the COMPLETED event. It just didn’t arrive at the webhook URL in that order. :slightly_smiling_face:

my question is how I handle the out of order webhooks. obviously what is happening right now is your webhook updates the status of the payment to completed so my system changes the payment status to completed. then it updates it to in_progress and my systems changes it to in_progress.

I am asking if I am safe to put some code that detects if it is already completed do not update to in_progress? THe reason I am asking is because I dunno maybe you guys change payments to in_progress again if someone charges back or there is a refund and I need to be aware that might happen.

According to the team at the moment the best you can do is track the updated_at timestamp on the event level ( don’t confuse it with any updated_at on the object) for some period of time before confirming what order to process in. :slightly_smiling_face:

all good, it would be better if this was a promise that just resolved when done? rather than webhooks. or your webhooks should join a queue and always be sent in order.

But I can work with it, thank you.

We’re constantly working to improve our features based on feedback like this, so I’ll be sure to share your request to the API product team. :slightly_smiling_face:

Very easy. Here is the answer.

Do not update ‘COMPLETED’ transaction to other terminal status. Make sure that each transaction has unique REFERENCE created by your POS. Time to trigger ‘7 seconds or whatever time gap’ does not matter as long as you can pin-point transaction by using ‘REFERENCE’ created by your POS.

Terminal status will be ‘PENDING’ → ‘IN_PROGRESS’ → ‘COMPLETED’ but there is no guarantee your host (website or whatever) will be receiving ‘webhook’ as an exact order all the time. It is almost impossible in real world.

I do not think Square API product team need to do anything on this issue at all.

I never check ‘updated_at’ timestamp at all because there is no need to do so, as long as, I don’t update the terminal status if the status is ‘COMPLETED.’ ‘COMPLETED’ means completed. There is no reason to update ‘COMPLETED’ transaction again at all to ‘IN_PROGRESS’ or ‘PENDING.’

Wrapping up…
On webhook createTerminalCheckOut (cannot remember exactly… something like this), create or insert ‘TerminalCheckOut’. Update status. If webhook updateTerminalCheckOut is other than ‘COMPLETED’ on ‘COMPLETED’ checkOut, do not mess with this transaction. ‘COMPLETED’ means completed. There is no reason to mess up with ‘COMPLETED’ transaction at all. You might say ‘REFUND’ but it will be handled by Payment API, not by Terminal API.