Multi-State Title & Registration - Developer Guide
1. Overview & Introduction
The Multi-State Title & Registration API lets you submit and process cross-border vehicle title and registration transactions across U.S. jurisdictions through a single integration. Instead of building and maintaining a separate integration per state DMV, you send one transaction to Vitu and receive back jurisdiction-specific status, fees, forms, and confirmation data.
The central domain object is the transaction. A transaction represents one title/registration filing for a specific vehicle in a specific state. Every transaction carries a state and a transaction type; together these determine which jurisdiction-specific data shape applies. The spec models this with a discriminated union keyed on state — the base transaction schema resolves to a per-state variant (for example, a California transaction versus a Florida transaction), each carrying its own state-specific vehicle schema and rules. This is the most important structural fact about the API: the required and permitted fields of a transaction depend entirely on its state. Consult the per-state schema in the spec for the jurisdiction you are filing in.
A transaction moves through a lifecycle: it is created, optionally updated, and then committed for final submission; it can also be cancelled. Alongside the core transaction, the API exposes derived resources scoped to a transaction: its fees, its forms/documents (including downloadable PDFs and a coversheet), and its status. There are also transaction types (see the spec's transaction-type enumeration — e.g. interstate, EVR, DMV desk), which influence status shape and callback content. Status is itself polymorphic by transaction type; the spec resolves the status schema on the transactionType discriminator.
Environments. The API is served from a single host template with an environment variable. The spec defines three environments — a production environment and two non-production environments (stage and test). Treat the production environment as the default only when you intend to submit real filings; do all integration work against a non-production environment. See the spec's servers block for exact URLs.
Access and sensitivity. All operations require OAuth 2.0 client-credentials authentication (see §3). Transactions contain regulated and personally identifiable data — VINs, owner names, addresses, and (at commit time) signer contact details. Treat all request and response payloads as sensitive; see §"Data Sensitivity" below.
Corresponding Title & Registration Notifications product: The Title & Registration Notifications product serves as a complementary offering to this Multi-State Title & Registration service. Together, the transaction and notification capabilities provide a complete ecosystem for both initiating vehicle transaction requests and staying informed of relevant updates through secure, automated notifications. See that product in the Catalog for more details.
2. Getting Started / First Call
Prerequisites
- An OAuth 2.0 client-credentials grant (client ID and secret) issued by Vitu.
- Network access to a non-production environment host (see the spec's
serversblock). - The ability to receive an HTTPS callback if you want asynchronous status notifications (optional; see §"Asynchronous / Webhook Patterns").
Obtain access
Credentials are obtained from the Key Management area within Vitu's Developer Portal. Use them to request a bearer token from the token endpoint defined by the keycloak security scheme in the spec.
Minimal happy path
The shortest path to a submitted filing:
- Get a token. Exchange your client credentials at the token endpoint for a bearer access token (see §3).
- Create the transaction. Call the transaction-creation operation (
CreateTransaction) with a state-specific transaction body. Because the body is discriminated onstate, populate the fields required by that state's schema. The create operation is asynchronous — it acknowledges receipt rather than returning a finished result (see §6). - Correlate the result. On create you may supply your own reference number; you can later resolve it to the numeric transaction identifier using the reference-lookup operation (
GetTransactionIdByRefNumber). Both the numeric ID and the reference UUID are accepted wherever a transaction identifier is required. - Check readiness. Poll the status operation (
GetTransactionStatus) and, if needed, retrieve calculated fees (GetTransactionFees) and produced forms (GetTransactionForms). - Commit. When the transaction is ready and fees/forms are acceptable, call the commit operation (
CommitTransaction) with the finalization body (shipping details are required at this step).
Refer to the spec for the exact request and response shapes of each operation named above.
3. Authentication & Access Walkthrough
The API uses a single security scheme: OAuth 2.0 client-credentials, registered in the spec as keycloak with the scope oneapi:access. The spec's securitySchemes block is the formal definition; this section covers only the operational how-to.
There is only one authentication scheme. There is no API-key or interactive/authorization-code alternative — do not build for one.
Obtaining and attaching a token
- Retrieve your client ID and secret from the Key Management area of Vitu's Developer Portal.
- Perform a client-credentials token request against the token endpoint from the
keycloakscheme, requesting theoneapi:accessscope. - Attach the returned access token as a bearer token on every API request.
Token lifecycle
- Tokens are bearer tokens with a finite lifetime. Cache and reuse a token until shortly before it expires rather than requesting one per call.
- Client-credentials grants have no refresh token; when a token nears expiry, request a new one with your client credentials.
- On a
401(unauthenticated) response, obtain a fresh token and retry once. A persistent401after re-authentication indicates a credential or configuration problem, not an expiry problem. A403(authenticated but not permitted) is not retryable — it means your client lacks permission for the resource; do not loop.
Environment differences
The same grant type applies in all environments. Use non-production environments for integration and testing; only the production environment produces live filings.
4. Key Concepts & Glossary
Transaction. The primary resource: one title/registration filing for one vehicle in one state. Its data shape is selected by its state discriminator, so field requirements are jurisdiction-specific. A transaction also has a transaction type, which affects status shape and callback content.
Transaction type. A classification (see the spec's transaction-type enum — e.g. Interstate, EVR, DMV Desk) supplied as a query parameter on transaction operations and used as the discriminator for status responses. Different types surface different status and callback schemas.
Vehicle. The vehicle being titled/registered, embedded in the transaction. Like the transaction, the vehicle schema is state-specific and discriminated on state. Some states mark the vehicle as required on the transaction; check the per-state schema.
Trade-in vehicle. An optional collection on most state transactions representing vehicles traded in against the purchase. Shape is state-specific.
Identifiers. A transaction is addressable by either its numeric transaction ID or its reference UUID (refNumber). The reference is yours to supply at creation; the reference-lookup operation maps a reference UUID to the numeric ID.
Fees. Jurisdiction-calculated charges derived from the transaction (state fees, taxes, vendor fees, and their details). Read-only; retrieved per transaction.
Forms / documents. The set of documents a transaction produces (each with metadata such as whether it is required, selected, or signed). Documents can be listed, downloaded individually or in bulk as PDF, generated blank, and targeted to a recipient (e.g. dealer, customer, lender). A coversheet for shipped documents is a separate downloadable artifact.
Status. The current state of a transaction, polymorphic by transaction type. Depending on type it may include an event history, audit errors, shipment/indicia details, an assigned plate, or a deal status. Treat the type-appropriate status field — not the HTTP code — as the signal of progress.
Commit / finalize. The act of final submission. The finalization body requires shipping information and may carry plate-destination and signer details.
Callback. An optional asynchronous notification POSTed to a URL you supply at creation. Its body is polymorphic (success, failure, and type-specific variants). See §"Asynchronous / Webhook Patterns."
Lifecycle and dependencies
CreateTransaction ──► (transaction exists)
│
- ► UpdateTransaction (revise before commit)
- ► GetTransactionFees (read derived fees)
- ► GetTransactionForms (list produced documents)
│ └──► DownloadTransactionForms / DownloadTransactionDocument
- ► GetTransactionStatus (poll progress)
- ► CommitTransaction (final submission; requires shipping)
│ └──► DownloadTransactionCoversheet (once shipping docs assigned)
- ► CancelTransaction (cancel)
All derived resources (fees, forms, status, coversheet) and all lifecycle transitions require the transaction to exist first.
5. Common Use Cases & Integration Patterns
Scenario A - Submit a new title & registration filing
CreateTransaction— create the transaction using the state-specific body. Supply your own reference number so you can correlate results. Optionally supply a callback URL to receive asynchronous updates.GetTransactionStatus(or await a callback) — wait until the transaction has been processed far enough to produce fees and forms.GetTransactionFees— review calculated charges before committing.GetTransactionForms— confirm the documents produced and which are required/selected.CommitTransaction— finalize with shipping details.
Ordering/dependencies: create must precede everything; commit should follow fee/form review. Because create is asynchronous, do not assume fees or forms exist immediately after create returns.
Scenario B - Revise a draft before commit
CreateTransaction.UpdateTransaction— send a corrected state-specific body.- Re-check
GetTransactionFees/GetTransactionFormsif your change affects them. CommitTransaction.
Scenario C - Retrieve and distribute documents
GetTransactionForms— enumerate documents and their IDs.DownloadTransactionDocument— fetch a specific document as PDF (optionally as a blank form), orDownloadTransactionFormsto retrieve documents, optionally scoped to a recipient target.DownloadTransactionCoversheet— fetch the shipping coversheet once it is ready (this operation reports "not ready yet" distinctly from "not found" — see §6).
Scenario D - Correlate an existing filing by your reference number
GetTransactionIdByRefNumber— resolve your reference UUID to the numeric transaction ID.- Use the resolved ID (or the reference) on any transaction-scoped operation.
Recommended patterns
- Prefer callbacks over polling where you can host an HTTPS endpoint: register a callback URL at create time and react to status-change notifications. Fall back to polling
GetTransactionStatuswhere you cannot receive callbacks. - Treat create/update/commit/cancel as asynchronous. They acknowledge intent; confirm outcomes via status or callback.
- Correlate by your own reference. Always set a reference number at creation so you can reconcile asynchronous callbacks and later look-ups.
6. Behavioral & Operational Notes
- Create, update, commit, and cancel are asynchronous. These operations acknowledge receipt (an accepted-style response) rather than returning a completed result. Do not treat a successful HTTP response as proof the filing succeeded; confirm via
GetTransactionStatusor a callback. - Success is a status field, not an HTTP code. The meaningful outcome lives in the type-appropriate status/
universalStatusfield of the status or callback payload. An accepted acknowledgement can still be followed by a failure callback. - Eventual consistency of derived resources. Fees, forms, and the coversheet are produced by processing and may not exist immediately after create. The coversheet download explicitly distinguishes "not ready yet, will be available eventually" from "not found" — poll rather than treating the not-ready response as an error.
- State-dependent validation. Because the transaction body is discriminated on
state, validation rules and required fields differ per jurisdiction. A body valid for one state will not necessarily be valid for another. - Identifier interchangeability. Transaction-scoped operations accept either the numeric ID or the reference UUID as the path identifier. Choose one consistently to avoid confusion when correlating.
- Update semantics (replace vs. merge) are unspecified. The update operation takes the same full transaction body as create. Whether it replaces the entire transaction or merges fields is not defined in the spec. Flag for the API owner: document update semantics. Until then, send a complete, self-consistent body on update.
- Callback signing. When a callback HMAC key is configured, callbacks are signed (HMAC/SHA-256, base-64 encoded per the spec's callback description).
7. Asynchronous / Callback Patterns
Create, update, commit, and cancel each support an optional callback: supply an HTTPS callback URL at request time and Vitu will POST a status-change notification to it. The callback body is polymorphic — success, failure, and transaction-type-specific variants (see the callback schema in the spec).
- Correlation: callbacks carry transaction identifiers and (in most variants) the VIN; use these plus your own reference number to correlate a callback back to the originating request.
- Delivery expectations: the callback is delivered when the transaction's status changes; your endpoint should return a success acknowledgement on receipt.
- Verification: when an HMAC key is configured, callbacks are signed (see the callback-signing note in §6 and its open flag).
Corresponding Title & Registration Notifications product: The Title & Registration Notifications product serves as a complementary offering to this Multi-State Title & Registration service. Together, the transaction and notification capabilities provide a complete ecosystem for both initiating vehicle transaction requests and staying informed of relevant updates through secure, automated notifications. See that product in the Catalog for more details.
8. Environments & Sandbox Access
The spec defines one production environment and two non-production environments (stage and test) via the server host template. Non-production environments are for integration and testing and should not be used for live filings; the production environment produces real title/registration submissions. Obtain credentials from the Key Management area of Vitu's Developer Portal.
9. Rate Limiting & Quotas
Every operation can return a "too many requests" response when a rate limit is exceeded; the response indicates that the caller should retry after the window resets. Treat this class of failure as retryable with backoff (see the agent failure rules).
10. Pagination Conventions
List-style operations (transaction forms, transaction fees) use offset-based pagination via shared limit and offset query parameters (see the spec's shared parameter definitions for bounds and defaults). Advance through pages by increasing the offset by the page size.
11. Error Handling & Troubleshooting
Errors are returned using the spec's error array schema (a list of messages). Handle them by class rather than by memorizing specific codes:
| Class | Meaning | Retryable? | Action |
|---|---|---|---|
| Auth (unauthenticated) | Missing/expired/invalid token | Once, after re-auth | Fetch a fresh token, retry once; if it persists, check credentials |
| Auth (forbidden) | Authenticated but not permitted | No | Do not retry; verify client permissions / scope |
| Validation (bad request) | Malformed or state-invalid body | No | Fix the payload against the per-state schema; resubmit |
| Not found | Unknown transaction/document identifier | No | Verify the ID/reference; for freshly created resources, allow for eventual consistency |
| Rate limit (too many requests) | Throttled | Yes | Back off and retry after the window resets |
| Server error | Server-side failure | Yes, cautiously | Retry with exponential backoff; reconcile via status before retrying mutating calls |
Backoff convention: for retryable classes, use exponential backoff with jitter and a bounded retry count. Because create/commit idempotency is unspecified (see §6), reconcile via GetTransactionStatus or reference-lookup before retrying a mutating operation whose outcome is unknown.
12. Data Sensitivity & Compliance Notes
Transactions and their callbacks carry regulated and personally identifiable information — VINs, owner and signer names, addresses, contact details, and jurisdiction filing data. Handling expectations:
- Transmit only over TLS (the spec's callback URL pattern requires HTTPS; apply the same to your own endpoints).
- Store payloads only as long as needed; treat logs containing request/response bodies as sensitive.
- Restrict access to tokens and to stored transaction data.
13. Support & Resources
For any API assistance, contact Vitu's API support team at [email protected].