Handling errors
Every failure from publish, updatePoints, heartbeat, or get is a GoodchargeError, carrying a status, a code, details (an array of { path, message }), and a retryAfter. The one exception is a fetch that misbehaves, such as a custom one resolving to something other than a Response: its own error comes through unchanged (see unknown_error). What you do about a GoodchargeError depends less on the exact code than on which of these five situations it falls into.
Retried automatically
A 429 (too many requests), a 5xx, a timeout, or a network error are all retried for you, up to maxRetries (3 by default). goodcharge allows one request per second per key, so an occasional 429 under normal use is expected and handled without any code on your side.
Thrown synchronously
An invalid_api_key or an invalid_option means something is wrong with how you built the GoodchargeStation or called startHeartbeat: a malformed key, an out-of-range timeoutMs, maxRetries or intervalMs, or an invalid metricsLabel. Both are thrown synchronously, at the constructor or at startHeartbeat itself, before any request is made.
Neither call is asynchronous, so this never reaches you as a rejected promise. Wrap the constructor call or startHeartbeat itself in a plain try/catch; an await or a .catch() further down does not see it.
The metrics helpers throw invalid_option synchronously too, for a list that is not an array of stations or that holds two stations with the same label: metricsText and metricsResponse when you call them, metricsHandler when you create the handler, and registerGoodchargeMetrics when it registers (also when the goodcharge metrics are already on that registry).
Rejected before any request
publish and updatePoints reject with invalid_option when the body you pass cannot be serialised to JSON, for example a circular object or a BigInt. This one does arrive as a rejected promise, like every other failure of those calls, but the SDK neither calls the API nor retries it. Fix the value you pass.
Needs a payload fix
An invalid_payload means the request reached goodcharge but the data itself failed validation. Its details array lists exactly what to fix, one { path, message } entry per problem. Correct those fields and send the request again.
Needs a prior call
A not_published error means you called updatePoints or heartbeat before ever calling publish for this station. Call publish first; the other two calls depend on it.
Retry-After
When a 429 or 5xx response carries a Retry-After header, the SDK honours it (whether it is given in seconds or as an HTTP date) before its automatic retry. If that Retry-After is more than 60 seconds out, the SDK does not wait and retry on its own: it throws the error instead, still carrying retryAfter, so your code can decide whether and when to try again.
The full table of error codes, HTTP statuses, and what to do about each one lives in the SDK reference.