OData V4
RAP / CDS / ODataintermediate

OData V4 Part 1: The OData V4 Contract — Metadata, Keys, Navigation, Queries

Key takeaway

Read an OData V4 service like a contract: service document, $metadata, entity sets, keys (including IsActiveEntity for draft), navigation, and the query options $select, $filter, $orderby, $top, $skip, $count, $expand and $search.

What this complete series covers

Learn SAP OData V4 with RAP from metadata and service binding through CRUD testing, actions, batch requests, troubleshooting and ETag concurrency.

Who it is for
Best for SAP consultants, developers, and learners who want a practical understanding of OData V4.
Prerequisites
Basic ABAP and ADT in Eclipse are recommended. The series explains the RAP/CDS/OData concepts as they are introduced.
Final outcome
By the end, you should be able to publish, test and troubleshoot an OData V4 RAP service and explain the boundary between the API protocol and RAP business logic.
  1. Part 1: OData V4 Part 1: The OData V4 Contract — Metadata, Keys, Navigation, Queries

    Understand the OData V4 contract exposed by RAP: service root, metadata, entity sets, keys, navigation, query options, and why clients must treat the service metadata as the authoritative API contract.

  2. Part 2: OData V4 Part 2: Publishing a RAP Service with an OData V4 Binding

    Follow the RAP service-exposure chain from CDS projection to service definition and OData V4 service binding, keeping business logic independent from the protocol layer.

  3. Part 3: OData V4 Part 3: Test CRUD Requests, Payloads and Responses

    Test the published RAP OData V4 service with metadata, GET, POST, PATCH and controlled error scenarios.

  4. Part 4: OData V4 Part 4: Actions, Functions and Batch Processing

    Model non-CRUD OData V4 operations correctly—functions for side-effect-free reads, actions for commands that can change state, and batch/change sets for grouped HTTP requests with

  5. Part 5: OData V4 Part 5: Troubleshooting HTTP Errors, Metadata and Payloads

    Troubleshoot OData V4 layer by layer using the exact request, service metadata, HTTP status, backend user, RAP messages, and client capabilities instead of guessing from a generic Fiori or API error.

  6. Part 6: OData V4 Part 6: ETags and Optimistic Concurrency

    Use ETags to prevent lost updates in RAP/OData V4 by making a client prove that the entity version it modifies is still current, while understanding draft total-ETag and locking interactions.

System and release assumptions: Examples target recent SAP S/4HANA / ABAP Cloud capabilities. RAP, CDS, OData, and Fiori Elements syntax and tooling can differ by ABAP platform release.

Explanation

📌 KEY POINTS
✅ $metadata is the contract: entity types, keys, properties, navigation, actions.

✅ Query options shape the response: $select, $filter, $orderby, $top/$skip, $count, $expand.

✅ Draft-enabled RAP entities have a second key: IsActiveEntity.

💡 Always $select only the fields you need — it is the simplest performance win.

━━━━━━━━━━━━━━━━━━━━
▶ WHAT THIS SERIES COVERS

  • Part 1 — the OData V4 contract (this lesson)
  • Part 2 — publishing a RAP service with an OData V4 binding
  • Part 3 — testing CRUD requests, payloads and responses
  • Part 4 — actions, functions and batch
  • Part 5 — troubleshooting HTTP errors
  • Part 6 — ETags and optimistic concurrency

━━━━━━━━━━━━━━━━━━━━
▶ WHAT ODATA IS

OData is a standard REST protocol for typed business data over HTTP. RAP generates the OData service from your projections and behavior, so you do not write HTTP handlers — but you must understand the contract to test, integrate and troubleshoot.

━━━━━━━━━━━━━━━━━━━━
▶ 1. THE SERVICE ROOT AND SERVICE DOCUMENT

A RAP OData V4 UI service URL looks like:

/sap/opu/odata4/sap/zui_purchreq_o4/srvd/sap/zui_purchreq/0001/

  • zui_purchreq_o4 — the binding, zui_purchreq — the service definition, 0001 — the service version.

GET on the root returns the service document: the list of entity sets.\n\n━━━━━━━━━━━━━━━━━━━━\n▶ 2. $METADATA — THE CONTRACT\nGET …/$metadata returns XML describing:

  • EntityType — structure: Property (name, type, nullable, maxLength), Key.
  • EntitySet — the collection you query (PurchaseRequest).
  • NavigationProperty — relationships (_Item) with NavigationPropertyBinding to target sets.
  • Action / Function — operations (approve).
  • Annotations — UI and semantics vocabularies (for Fiori).

Every client relies on this; changing it can break clients (Service Definitions Part 3).

━━━━━━━━━━━━━━━━━━━━
▶ 3. KEYS AND ENTITY ADDRESSING

  • Single entity: …/PurchaseRequest(RequestUUID=<uuid>)
  • With draft: …/PurchaseRequest(RequestUUID=<uuid>,IsActiveEntity=true) — active version; false = draft.
  • Navigation: …/PurchaseRequest(…)/_Item

━━━━━━━━━━━━━━━━━━━━
▶ 4. QUERY OPTIONS

  • $select=RequestID,Description — only these properties.
  • $filter=Status eq 'S' and TotalAmount gt 1000 — operators: eq, ne, gt, ge, lt, le, and, or, not; functions: contains(Description,'chair'), startswith(…).
  • $orderby=CreatedAt desc
  • $top=20&$skip=40 — paging.
  • $count=true — total number of matching rows in the response (@odata.count).
  • $expand=_Item($select=ItemNo,Quantity;$filter=Quantity gt 5) — include related entities, with nested options.
  • $search=chair — free-text search (if the entity is searchable).

━━━━━━━━━━━━━━━━━━━━
▶ 5. THE JSON RESPONSE

{ "@odata.context": "…$metadata#PurchaseRequest", "@odata.count": 57, "value": [ { "RequestID": "4711", … } ] }

Single entities return the object directly, with "@odata.etag" if an ETag is defined (Part 6).

━━━━━━━━━━━━━━━━━━━━
▶ V4 VS V2 IN ONE MINUTE

V4 is the current standard for RAP: JSON by default, richer query syntax (nested $expand options), cleaner actions/functions, better batch. V2 remains for older clients (OData V2 topic).

━━━━━━━━━━━━━━━━━━━━
▶ STEP BY STEP

  1. Open the service binding, copy the service URL, append $metadata.
  2. Find the EntityType PurchaseRequestType, its keys and the _Item navigation.
  3. Run the queries in the code example in a browser or REST client.

✅ CHECKPOINT: you can read $metadata and write any read query by hand.

Code example

ABAP Code
### Service root (UI binding, version 0001)### {root} = /sap/opu/odata4/sap/zui_purchreq_o4/srvd/sap/zui_purchreq/0001 ### 1. Service document and contractGET {root}/GET {root}/$metadata ### 2. List with only needed fields, filter, order, paging and total countGET {root}/PurchaseRequest?$select=RequestID,Description,Status,TotalAmount,CurrencyCode    &$filter=Status eq 'S' and TotalAmount gt 1000    &$orderby=TotalAmount desc    &$top=20&$skip=0&$count=true ### 3. One entity (draft-enabled BO: two key parts)GET {root}/PurchaseRequest(RequestUUID=4c2a…-…,IsActiveEntity=true) ### 4. Navigation and expand with nested optionsGET {root}/PurchaseRequest(RequestUUID=4c2a…,IsActiveEntity=true)/_ItemGET {root}/PurchaseRequest?$select=RequestID    &$expand=_Item($select=ItemNo,Quantity,Price;$filter=Quantity gt 5;$orderby=ItemNo) ### 5. Text functions and searchGET {root}/PurchaseRequest?$filter=contains(Description,'chair')GET {root}/PurchaseRequest?$search=chair ### Response (shortened)# {#   "@odata.context": "$metadata#PurchaseRequest(RequestID,Description,Status,TotalAmount,CurrencyCode)",#   "@odata.count": 57,#   "value": [#     { "RequestID": "4711", "Description": "Office chairs", "Status": "S",#       "TotalAmount": 3600.00, "CurrencyCode": "EUR" }#   ]# }

Real project scenario

A reporting tool pulled purchase requests via OData without $select and with $expand=_Item on every call. Each response contained all header fields plus all items, and nightly extraction took hours and sometimes timed out.
After reading the $metadata with the integration team, they changed the calls to $select only the six needed fields, filtered on LastChangedAt for delta loads, paged with $top/$skip, and expanded items only when needed. Extraction time fell to minutes, and the load on the backend dropped accordingly.

Common mistakes

  • Querying without $select and transferring every field.
  • Forgetting IsActiveEntity for draft-enabled entities and getting "not found".
  • Expanding to-many navigation everywhere.
  • Paging without a stable $orderby.
  • Treating $metadata as optional instead of the contract.
  • Using V2 syntax (e.g. substringof) in V4 requests.

Best practices

  • Start every integration by reading $metadata.
  • Always $select; filter server-side; page with $top/$skip and $orderby.
  • Use $count=true for UIs that show totals.
  • Use nested $expand options to limit expanded data.
  • Use V4 for new RAP services; V2 only for legacy clients.

Interview angle

Questions: "What is in OData $metadata?", "Explain $select, $filter and $expand", "How do you address a draft instance in OData V4?"
Strong answer: $metadata defines entity types, keys, properties, entity sets, navigation, actions and annotations — the contract. Query options: $select for fields, $filter with operators and functions, $orderby, $top/$skip paging, $count, $expand with nested options, $search. Draft entities include IsActiveEntity in the key. Mention the RAP V4 URL anatomy (binding, service definition, version).

Practice this lesson

Quick check

1. A third-party integration requests every property and expands three to-many navigations on each call. What should change first?

2. Which OData V4 query returns only two fields of submitted requests with a total count?

3. What is the best source for the public entity-set and property names of an OData V4 service?

Interview questions

1. Explain the OData V4 contract: what does $metadata contain and which query options exist?

Answer it in your own words first, then compare.

2. Why should you inspect OData V4 metadata before manually constructing CRUD requests?

Answer it in your own words first, then compare.

Practice more with Interview AI →

Reference-verified: the steps are checked against official SAP documentation and tutorials, and object and field names in the sample code are checked for consistency. The code has not been compiled or run on an SAP system by ERPClimb. Syntax marked release-dependent varies by SAP release, so check it in your own system.

More lessons in this topic

Interview questions on this topic

Related SAP topics