An access token lasts four hours (expires_in 14400), and an expired one answers 403, not 401. Exchange the refresh token at /oauth/token for a new one, with client_id and, for a server, client_secret in the body; then send the request again.
If the refresh itself fails with 400 invalid_grant, the refresh token is no longer good: it expires sixty days after it was issued, and it can be exchanged fifty times. On the fiftieth exchange the answer carries a new refresh token and the old one stops working, so a client that kept only the first one is locked out after fifty refreshes. Store the refresh token from every answer. When it has expired, someone has to sign in as the integration's user again.