Executive Summary: When a Cobalt live Secretary of State lookup returns retryId and cachedData together, the integration has one open request with two kinds of information: process identity and an interim cached observation. Store them under one lender-owned request key, keep the cached payload immutable, and reserve a separate slot for the completed live result. That model prevents an early record from looking final and prevents the later result from erasing what the workflow knew while it was pending.
What Does the First Incomplete Response Represent?
What does retryId identify?
Cobalt's public SOS API reference describes retryId as an identifier returned for a longer-running request and used to check status and retrieve data when the request completes.[1] Its Help Center says 202 + Incomplete means the state search is still processing, not that it failed.[2]
The identifier therefore belongs to the open operation. It does not describe the age or quality of a business record, and it does not replace the lender's application or verification ID.
What does cachedData identify?
Cobalt's September 2026 feature release adds an optional cached match to that same incomplete response when one is available. The array can include a business title, status, normalized status, registration state, and updatedAt. The live search continues under the existing request.
These fields describe an interim observation. They are not a second lookup, and they do not turn the top-level response into a terminal result. Cobalt's public status guide already distinguishes incomplete processing from completed results, cached fallback, no results, and failure.[3]
Model the first response as one request record plus one optional observation, not as two independent verifications.
Why Should the Lender Use Its Own Parent Request Key?
Why is retryId not enough for downstream identity?
retryId connects later Cobalt status checks to the original API operation. A lender-owned key connects that operation to the application, applicant, product, policy version, and intended business effect. Public documentation does not define retryId as a complete idempotency key for the lender's systems.
A useful parent key may already exist as an application-verification ID. Store retryId as provider correlation data beneath it. This keeps a provider process identifier from becoming the sole join key for credit-file history.
Which fields belong on the parent request?
The parent should hold context that remains stable across interim and final observations:
• Lender request key. Stable identifier for one logical verification attempt.
• Application and entity references. Internal IDs, not customer data copied into editorial systems.
• Exact search inputs. Business name or state identifier, state, and material filters.
• Requested delivery path. Polling or callback, plus any screenshot request state.
• Provider correlation. retryId or documented callback request identity.
• Current process state. Accepted, live pending, live complete, failed, or review required.
• Policy version. The lender rule set that governed any interim action.
Microsoft's asynchronous request-reply pattern similarly attaches a request identifier to a status resource and keeps the pending operation separate from the eventual result.[4] The exact storage technology is up to the lender.
What Belongs in the Interim Observation?
Which provider fields should be preserved?
Preserve the exact cached payload before normalizing it. Then store a normalized view for internal use if needed. The raw observation gives later reviewers a way to explain field mapping or schema changes.
A proposed customer-owned record can look like this:
{
"verificationRequestId": "vr_example_001",
"provider": "cobalt_sos",
"providerRetryId": "72f06828-f593-40f1-9b4d-65a248e78869",
"processState": "live_pending",
"interimObservation": {
"sourceType": "cached",
"receivedAt": "2026-09-16T08:15:00Z",
"updatedAt": 1788994658510,
"rawRecord": {
"title": "FF PIZZA LLC",
"status": "Active",
"normalizedStatus": "Active",
"stateOfSosRegistration": "CA"
}
},
"finalObservation": null
}
The names are an implementation example, not a Cobalt schema. Do not add undocumented provider fields to the API contract.
Keep the raw response and the normalized record linked by a stable observation ID. If normalization rules change, create a new derived version rather than rewriting the bytes received from Cobalt. A database constraint can also prevent two workers from creating separate interim observations for the same lender request, provider retry identifier, and response phase. These are customer-side controls, not requirements imposed by the API. Their purpose is to preserve the exact input while letting operations query a predictable internal shape.
Why store both updatedAt and receivedAt?
updatedAt describes when the cached record was updated. receivedAt describes when the lender obtained it. They answer different questions. Cobalt says cached records do not auto-expire and provides createdAt and updatedAt so consumers can evaluate recency for their use case.[5]
The lender can calculate age when the record is evaluated and store the rule outcome separately. A later reviewer can then reconstruct both how old the provider record was and when the system acted on it.
Why Should the Final Result Be Stored Separately?
What history disappears when final data overwrites cached data?
An overwrite removes evidence of what the user saw, which timestamp the rules evaluated, and why a reversible action occurred. That may not matter when the lender ignores cachedData. It matters immediately when the data fills a screen, starts a queue, or populates a comparison.
Cobalt's new feature also warns that cached and live matches may differ because Cobalt's cached matching and a state's search behavior are not identical. A separate final observation makes that variance visible rather than turning it into an unexplained field change.
How should the final transition work?
When the completed live result arrives, perform an idempotent transition:
• Verify the parent. Resolve the lender request key and provider correlation.
• Store final bytes. Preserve the raw live result and receipt time.
• Compare observations. Record whether stable identifiers or material fields differ.
• Choose terminal state. Complete when policy passes, or route to review when a variance matters.
• Preserve prior state. Keep the interim observation and any action history.
AWS describes idempotency as repeated calls having the same state effect as one call and recommends it for retry workflows.[6] That principle protects the final transition when a poll or callback is processed twice.
This design is narrower than Cobalt's published retry and graceful-failure guide. That article explains retry behavior. This one defines what to persist when useful data accompanies the open job.
What Should Happen When cachedData Is Missing?
Why should the parent record still exist?
The parent describes the open live request, whether or not an interim match exists. If cachedData is absent, keep interimObservation empty and preserve the pending state. Cobalt's Help Center says a cache miss does not prove that the business is absent from the state registry.[7]
Do not create a terminal no-match, insert an empty business record, or start a second independent verification merely because the optional array is missing.
Which absence states need separate codes?
Separate at least these conditions:
• No cached match available. Live pending continues.
• Cached record rejected by age policy. Observation exists but is not used.
• Cached record rejected by match policy. Observation exists but routes to review or no interim use.
• Final live no-match. The completed state search found no qualifying record.
• Request error or invalid retry. Provider processing cannot continue under the current identifier.
Cobalt's response-status guide gives distinct meanings to incomplete, cache miss, cached fallback, failure, and invalid retry.[3] Those meanings should survive inside the lender's model.
How Should Polling and Callbacks Update the Record?
What is the common state machine?
Polling and callback delivery are transports for the same business state. Cobalt supports both, with callbacks recommended for long-running or batch workflows and polling available when an inbound endpoint is not practical.[8]
Use one allowed-transition map:
| Current state | Event | Next state | Business effect |
|---|---|---|---|
| Accepted | Incomplete, no cache | Live pending | None |
| Accepted | Incomplete, cache present | Live pending plus interim stored | Optional reversible action |
| Live pending | Duplicate incomplete | Live pending | None |
| Live pending | Final live result | Complete or review | One terminal transition |
| Complete | Duplicate final result | Complete | No repeated decision |
The transport may differ, but the request identity and allowed effects do not.
How should duplicate delivery be controlled?
Cobalt's batch guidance recommends backoff and idempotent queues.[9] The Standard Webhooks specification also recommends unique event identifiers and idempotency handling to prevent accidental processing of a repeated event.[10]
The approved Cobalt sources do not promise exactly-once or ordered webhook delivery. Design the consumer so a duplicate event is harmless, and store a processing key or terminal-transition marker in the lender's system.
What Should Be Logged for Later Review?
Which event fields make the record explainable?
OWASP says application logs should record when, where, who, and what, including status, reason, HTTP status, and the response or action taken.[11] For this workflow, log the request key, provider identifier, search inputs, response state, cached payload hash or retained bytes, updatedAt, receipt time, final result, comparison outcome, and disposition.
NIST describes log management as handling event data across generation, transmission, storage, access, and disposal.[12] Retention, permissions, and redaction remain lender-owned policy. This article does not prescribe a legal schedule.
How does this support audit trails without overstating them?
The record can show what data was available, when it was available, and what the workflow did. That is operational traceability. It is not a claim that one JSON object satisfies a regulator, court, or examiner.
Cobalt's related article on automated credit-data audit trails places request identity, timestamp, source, result, and disposition in the same broader control record.
What Is the Smallest Safe Persistence Model?
Which pieces are essential for a first release?
Start with the minimum that preserves identity and finality: one lender request key, request inputs, provider retryId, process state, immutable interim observation, immutable final observation, timestamps, and one terminal-transition marker. Add derived views later.
Do not start by building a large data warehouse or a universal event model. The first production risk is more basic: losing the relationship between the cached observation and the still-open live job.
Where does Cobalt stop and lender policy begin?
Cobalt supplies the process identifier, optional cached observation, updatedAt, and completed live result. The lender decides storage technology, retention, idempotency, interim permissions, review thresholds, and all credit outcomes.
If your team wants to map Cobalt's incomplete and final SOS responses into an existing lending system, schedule a demo to review the integration states.
The correct model makes one fact impossible to miss: early data and final data can belong to the same request without having the same decision meaning.












.png)