What changes when the client runs unattended
A scheduled client has to supply the states a human used to provide: an authenticated session, a valid credential, a correct clock and a judgement about whether the response was useful. Each one becomes part of the program.
The failure modes change with them. An interactive run stops at the first error and a person reads it. An unattended run continues through a partial failure, writes a report with missing sections and exits with a success status, so the problem appears days later as a data gap.
Persist the session outside the process
A scheduled run starts with no memory, so the session has to live somewhere durable between runs. Store the access token, the refresh token, the account it belongs to and the time it was issued. Keep that file where the job can write, with permissions that match the sensitivity of a live credential, and out of the source tree.
- Refresh before the token expires. A refresh in the middle of a batch can fail halfway, so run it at the start of the job when the remaining lifetime falls below a margin, and set the margin larger than the longest expected run.
- Persist a rotated refresh token. Many services issue a new refresh token with each refresh and retire the old one. A job that keeps the original token in a config file works once and then fails on the next run.
- Lock the session file. Two overlapping runs will refresh at the same time, and the second refresh can retire the token the first one just saved. A lock file or a single worker prevents that race.
- Sign in again when refresh fails. Credential login is the fallback, and it needs the same care with any device identifier or verification step the flow requires.
Use the server's clock for signed requests
A client that signs a timestamp with the host clock breaks when the host clock drifts. The server compares the value against its own time and rejects anything outside a short window. A virtual machine that resumes from a snapshot can be minutes or hours off without any error appearing anywhere.
Ask the server for the time and keep an offset. A response Date header or a dedicated time endpoint gives a reference, and the client can compute the difference once per run and add it to every timestamp it signs. That offset survives a wrong host clock, while the host clock alone does not. Where a flow needs exact ordering rather than wall time, use a monotonic timer for the sequence and the server offset for the signed value.
Handle a rotated or revoked credential
Passwords change, sessions get revoked from another device, and services force a fresh login after a period or after an app update. Each is an expected event with a defined response rather than a surprise.
- Hold the credential in a secret store or an environment variable. Read it at run time so a rotation does not require a code change or a redeploy.
- Distinguish an expired session from a rejected credential. Refresh handles the first and a new login handles the second. Retrying the same expired token on a fixed interval produces a locked account.
- Stop after a small number of authentication failures. Back off, then raise an alert. A job that retries a bad password every minute will trip the service's own protection.
Detect breakage that the status code hides
An endpoint can answer 200 with a payload that no longer carries the data your job needs. The change usually arrives with a server release rather than with your code, so the check belongs in the job.
- Assert the shape of the payload. Check that the expected field exists and holds the expected type before the job uses it.
- Assert a plausible quantity. A list that is empty on a day when it is never empty is a signal even though the request succeeded.
- Record a run history. Save the status, the latency, the item count and a hash of the response shape for each run. A shape that changes between two runs stands out in that history and stays invisible in a status-only log.
- Send a canary call first. One cheap authenticated request at the start of the run confirms the session and the current API specification before the job spends its quota.
The result is a job that either completes with data you trust or reports a specific failure you can act on. SReverse builds these unattended clients from the APK and delivers the module with session handling, scheduling notes and documentation. Projects start at $120 and most are delivered in 24 to 72 hours.
Related work
Reviewed 28 September 2026 · SReverse research desk