I posted the general version of this in Tips & Tricks a couple of days ago: The OAuth failure that only shows up 30 days after your workflow works
This is the Pinterest half, since the actual numbers are what decide how you build it.
Pinterest v5 rotates the refresh token on every refresh. The refresh response carries a new refresh_token, and the one you just sent is spent. Store only the new access_token and you’ve thrown away the key to the next refresh.
Two clocks make it awkward:
expires_in: 2592000 on the access token, so 30 days. Publishing carries on working for a month after the mistake, which is why nothing in your recent changes explains the 401s when they start.
refresh_token_expires_in: 5184000, so 60 days from the original authorization. Past that the stored refresh token dies on its own and the only way back is the account owner doing a full re-auth. That’s the wall people actually hit.
Two things beyond just saving the new token:
Do the read, refresh and write as one atomic step per account, with a row lock, re-reading the token inside the lock. Otherwise two concurrent runs can both spend the same refresh token and the loser is left holding a dead one.
Refresh ahead of expiry instead of on demand. An account that goes quiet for a few weeks will otherwise cross the 60 day line without ever making a call.
Longer write-up with the concurrency case and a reference implementation: Why Pinterest integrations die quietly after two months – PinBridge
Posting it because there are a few “refresh token invalid” threads around and this is usually what’s underneath them.