OCPP is a standard, and standards by definition cover a defined set of cases. Real-world EV charging has vendor-specific features, regional variations, and emerging capabilities that don’t always fit the standard messages. (If you’re new to the protocol, what is OCPP is a good starting point.)
DataTransfer is OCPP’s extension point. It lets a vendor pass custom data between a charger and CSMS without modifying the protocol itself. Used carefully, it enables differentiated features. Used carelessly, it fragments the ecosystem.
This article covers what DataTransfer is, when it’s the right tool, and the patterns for using it well.
The basic concept
DataTransfer is a message that carries vendor-specific data. Both the charger and CSMS can send DataTransfer messages.
The structure (OCPP 1.6):
{
"vendorId": "com.example.charger",
"messageId": "VendorStatusReport",
"data": "{\"sensorReading\": 42.5, \"unit\": \"celsius\"}"
}
- vendorId — identifies the vendor / namespace. Conventionally a reverse-domain string.
- messageId — optional, identifies the specific message type within the vendor’s namespace.
- data — string payload, typically JSON-encoded.
The response:
{ "status": "Accepted", "data": "{\"ack\": true}" }
Statuses:
- Accepted — the recipient understood and processed the message.
- Rejected — the recipient understood but refused.
- UnknownVendorId — the recipient does not recognize the vendor ID.
- UnknownMessageId — the recipient recognizes the vendor but not the message.
The status flow the recipient walks through:
flowchart TD
A[Receive DataTransfer] --> B{Known vendorId}
B -->|No| C[UnknownVendorId]
B -->|Yes| D{Known messageId}
D -->|No| E[UnknownMessageId]
D -->|Yes| F{Process ok}
F -->|No| G[Rejected]
F -->|Yes| H[Accepted]
style H fill:#d4f4dd,stroke:#2a9d5c
style C fill:#f4d4d4,stroke:#c0392b
OCPP 2.0.1: DataTransferRequest
Same concept, slightly cleaner structure:
{
"vendorId": "com.example.charger",
"messageId": "VendorStatusReport",
"data": "{ \"sensorReading\": 42.5 }"
}
The 2.0.1 version supports more structured data via the device model variables system (coming soon) for many use cases that previously needed DataTransfer.
When DataTransfer is the right tool
A few scenarios where DataTransfer is appropriate.
Pre-spec features. A vendor wants to ship a new capability before the standard catches up. Example: a charger reporting detailed thermal data not covered by standard messages. DataTransfer lets the OEM ship it now; when the standard adds support, migrate.
Regional or regulatory data. Some jurisdictions require specific data formats. If OCPP doesn’t define them but the local market does, DataTransfer carries them.
Diagnostic or operational extensions. Vendor-specific diagnostics, configuration items, or operational metrics that the standard doesn’t cover.
Cross-component vendor coordination. When a vendor’s CSMS and chargers share a custom feature that uses non-standard data.
Forward-looking experimentation. Trying new ideas without standards-body coordination.
When NOT to use DataTransfer
Cases where DataTransfer is the wrong choice.
For data that fits standard messages. Don’t send temperature via DataTransfer if you can include it in MeterValues. The standard message is more interoperable.
To bypass authentication or authorization. DataTransfer goes through the same auth as other messages; don’t expect it to dodge security.
For large data transfers. Binary files belong in firmware update or log retrieval messages, not DataTransfer.
To replace device-model variables (in 2.0.1). Most configuration extensions should use the device model rather than DataTransfer.
For breaking changes to existing flows. If your “extension” significantly changes the meaning of standard interactions, that’s not an extension — that’s a fork.
Common DataTransfer patterns
A list of common real-world DataTransfer uses.
Vendor-specific status data
A vendor wants to expose charger temperature, fan speeds, internal voltages — operational data beyond what StatusNotification covers.
{
"vendorId": "com.acmecharge",
"messageId": "InternalDiagnostics",
"data": "{\"powerModuleTemp\": 65, \"cableTemp\": 32, \"fanRpm\": 1800}"
}
The CSMS shows this in vendor-specific dashboard panels.
Pricing display updates
A charger wants to show pricing on its display. OCPP 1.6 doesn’t have a clean way to push tariff data to chargers; some vendors use DataTransfer.
{
"vendorId": "com.networkops",
"messageId": "DisplayTariff",
"data": "{\"price\": \"€0.45/kWh\", \"validUntil\": \"2026-12-31\"}"
}
The charger shows the price on its screen. OCPP 2.1 has formalized this; pre-2.1, DataTransfer was the workaround.
Custom configuration
Vendor-specific configuration that doesn’t fit the standard ChangeConfiguration namespace.
{
"vendorId": "com.greatcharger",
"messageId": "SetCableUnlockMode",
"data": "{\"mode\": \"auto-unlock-on-session-end\"}"
}
Plug-and-play vehicle data
When the charger learns vehicle-specific data (model, battery size, capabilities) through ISO 15118 and wants to share with the CSMS.
{
"vendorId": "com.csmsvendor",
"messageId": "VehicleProfile",
"data": "{\"manufacturer\": \"Tesla\", \"model\": \"Model 3\", \"batteryCapacity\": 75}"
}
Diagnostic command channel
Vendor-defined diagnostic actions that the CSMS can trigger.
{
"vendorId": "com.diagvendor",
"messageId": "RunSelfTest",
"data": "{\"testType\": \"contactor-cycle\"}"
}
The charger runs the requested self-test and responds with results.
How OCPP 2.0.1 reduces DataTransfer need
A lot of what OCPP 1.6 used DataTransfer for is now native in 2.0.1.
Device model variables replace many configuration extensions. Custom variables under custom components are part of the standard mechanism.
Native tariff display in OCPP 2.1 replaces the DataTransfer hack.
Richer monitoring via VariableMonitoring replaces some vendor diagnostic extensions.
TransactionEvent’s richer data absorbs some session-related extensions.
Certificate management messages replace certificate-related DataTransfer hacks.
In a 2.0.1 implementation, you should reach for DataTransfer less often. The native messages cover most extension cases. The OCPP version comparison (coming soon) lays out what each release added.
Best practices
A few principles for using DataTransfer well.
Use a stable vendorId. Don’t change it across versions of your product. Backward compatibility matters.
Document messageIds. If you’re a vendor using DataTransfer, document the messageIds your chargers send and accept so CSMSes can integrate. Without documentation, your DataTransfer is opaque.
Validate inputs strictly. The data field is a string. Parse it carefully. Reject malformed JSON.
Return proper statuses. UnknownVendorId for unrecognized vendors, UnknownMessageId for unrecognized messages within a known vendor. Don’t return generic Rejected.
Don’t depend on DataTransfer for critical functionality. Standard messages should carry critical operations. DataTransfer is for the long tail.
Migrate when the standard catches up. When a future OCPP version absorbs your DataTransfer use case, migrate. The native messages are more interoperable.
Vendor-specific data in operations dashboards
A CSMS receiving DataTransfer from various vendors faces a UX challenge.
If the CSMS only knows OCPP standard messages, it can show standardized dashboards across vendors. DataTransfer data is opaque without vendor-specific code.
Patterns:
Vendor plugin model. CSMS supports plugins per vendor that interpret DataTransfer messages. New vendor = new plugin.
Pass-through display. Show DataTransfer payloads as raw data with vendor metadata; let operators inspect manually.
Standardize at the CSMS layer. The CSMS maps known vendor DataTransfer to standard internal representations for unified dashboards.
Each has trade-offs. Pure pass-through is easiest to implement; vendor plugins give the best UX but require maintenance.
Security considerations
A few security notes.
DataTransfer is authenticated like any other OCPP message. The bearer token / mTLS protect it.
Data field can carry sensitive information. If you’re using it for diagnostic data that includes user identifiers or session details, treat it as PII.
Vendor extensions can be a vector for bugs. Malformed DataTransfer payloads should be handled gracefully by the recipient — don’t crash, don’t expose stack traces.
Don’t use DataTransfer to bypass standard authorization. A DataTransfer that “starts a transaction” should still go through normal authorization checks.
The honest summary
DataTransfer is OCPP’s escape hatch for things the standard doesn’t cover. Used carefully, it enables differentiated features and forward-looking experimentation. Used carelessly, it fragments the ecosystem and creates interoperability friction. In OCPP 2.0.1, much of what DataTransfer used to carry has moved into native messages; reach for it less than you would have in 1.6. When you do use it, document, validate, and plan for migration to native when the standard catches up.