OData V4
RAP / CDS / ODataintermediate

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

Key takeaway

Publish a RAP service with an OData V4 binding end to end: create and publish the binding, understand the URL and versions, get a CSRF token, and run first read and write calls from a REST client.

Explanation

📌 KEY POINTS
✅ Binding type decides the consumer: OData V4 – UI (Fiori) or OData V4 – Web API (integrations).

✅ Activate + Publish is required; the binding shows the service URL.

✅ Every write request needs a CSRF token (fetched with a GET) — except in some API setups with other protection.

⚠️ 403 on POST is usually a missing CSRF token, not missing authorization.

━━━━━━━━━━━━━━━━━━━━
▶ WHERE WE ARE

Part 1 explained the contract. Now you make the service available and call it. (Service Bindings Part 2 covers the binding object in ADT; this lesson focuses on the OData V4 side and first calls.)

━━━━━━━━━━━━━━━━━━━━
▶ 1. CREATE AND PUBLISH THE BINDING

  • Right-click the service definition ZUI_PURCHREQ → New Service Binding.
  • Name ZUI_PURCHREQ_O4, binding type "OData V4 – UI".
  • Activate, then click Publish (on-premise, this publishes the service locally; in cloud systems publishing is part of the binding lifecycle).
  • The binding shows the service URL, the service versions and the entity sets with a Preview button.

━━━━━━━━━━━━━━━━━━━━
▶ 2. URL ANATOMY

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

  • /sap/opu/odata4 — OData V4 handler
  • zui_purchreq_o4 — binding (lower case)
  • srvd — UI binding path segment (Web API bindings use srvd_a2x)
  • zui_purchreq/0001 — service definition and version

━━━━━━━━━━━━━━━━━━━━
▶ 3. SERVICE VERSIONS

A V4 binding can contain several versions (0001, 0002) based on different service definitions. Use a new version for breaking changes (Service Definitions Part 3).

━━━━━━━━━━━━━━━━━━━━
▶ 4. FIRST CALLS FROM A REST CLIENT

Tools: browser (GET only), Postman/Insomnia, VS Code REST Client, or the ADT HTTP client.

  • GET the service root with basic authentication or your SSO setup.
  • For writes, first GET with header "X-CSRF-Token: Fetch"; the response returns a token and a session cookie.
  • Send POST/PATCH/DELETE with "X-CSRF-Token: <token>" and the same cookies.
  • Content-Type: application/json.

━━━━━━━━━━━━━━━━━━━━
▶ 5. DRAFT-ENABLED UI SERVICES

In a UI service with draft, a POST to the entity set creates a DRAFT (IsActiveEntity=false). To get active data you must call Activate (Part 4). For integrations, use a Web API service without draft (Service Definitions Part 5).

━━━━━━━━━━━━━━━━━━━━
▶ 6. AUTHORIZATION

The user needs a role with the service (start authorization for the OData service, typically via the IAM app/catalog in cloud or roles with S_SERVICE on-premise) plus the BO's own authorization objects.

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

  1. Create and publish ZUI_PURCHREQ_O4.
  2. Copy the URL; GET $metadata in the browser.
  3. In a REST client: fetch CSRF token, create a request (code example), read it back.
  4. Try the same POST without token → 403; add token → 201.

✅ CHECKPOINT: you can publish a V4 service and call it with any HTTP client. Part 3 goes deeper into CRUD payloads.

Code example

ABAP Code
### {root} = /sap/opu/odata4/sap/zui_purchreq_o4/srvd/sap/zui_purchreq/0001### Web API variant: /sap/opu/odata4/sap/zapi_purchreq_o4/srvd_a2x/sap/zapi_purchreq/0001 ### Step 1: fetch CSRF token (and session cookies)GET {root}/X-CSRF-Token: FetchAuthorization: Basic <base64 user:password># Response header:  x-csrf-token: 8nJ3k…== ### Step 2: create (UI service with draft -> creates a DRAFT)POST {root}/PurchaseRequestContent-Type: application/jsonX-CSRF-Token: 8nJ3k…== {  "Description": "Office chairs",  "CurrencyCode": "EUR"}# 201 Created# { "RequestUUID": "4c2a…", "IsActiveEntity": false, "Description": "Office chairs", ... } ### Step 3: read it back (draft version)GET {root}/PurchaseRequest(RequestUUID=4c2a…,IsActiveEntity=false) ### Typical first errors# 403 Forbidden + "CSRF token validation failed"  -> fetch token, send cookie# 404 Not Found                                   -> binding not published / wrong URL / version# 403 Forbidden (no CSRF message)                 -> missing role / service authorization

Real project scenario

An integration developer reported "403 Forbidden" for every POST to a new RAP service and requested more authorizations. The basis team added roles twice without effect. GET requests worked fine.
The response body actually said "CSRF token validation failed". The client never fetched a token. After adding the token fetch (GET with X-CSRF-Token: Fetch, then reuse token and cookies), all writes succeeded. The team documented the difference between a CSRF 403 and an authorization 403 in their integration guide.

Common mistakes

  • Activating the binding but not publishing it.
  • Using the UI binding for integrations and getting drafts instead of active data.
  • Sending writes without CSRF token or without the session cookie.
  • Misreading a CSRF 403 as missing authorization.
  • Wrong URL segment (srvd vs srvd_a2x) or version.
  • Testing only in the browser, which cannot send writes.

Best practices

  • One binding per consumer type: V4 UI for Fiori, V4 Web API for integrations.
  • Document the service URL, version and authentication for consumers.
  • Always implement CSRF handling in custom clients.
  • Test with a REST client and keep request collections in the repository.
  • Check the response body before changing authorizations.

Interview angle

Questions: "How do you publish a RAP OData V4 service?", "What does the service URL consist of?", "Why do POST requests fail with 403?"
Strong answer: create a service binding (V4 UI or Web API) on the service definition, activate and publish; the URL contains the V4 handler path, binding, service definition and version (srvd for UI, srvd_a2x for Web API). Writes need a CSRF token fetched via GET with X-CSRF-Token: Fetch and sent back with cookies; distinguish CSRF 403 from authorization 403 via the response body. UI services with draft create drafts on POST.

Practice this lesson

Quick check

1. Which URL segment identifies an OData V4 Web API binding in RAP?

2. A team exposed the base interface entity directly because it was faster than creating a projection. What is the main risk?

3. A POST returns 403 with "CSRF token validation failed". What is the fix?

Interview questions

1. An integration gets 403 on every POST to a new RAP V4 service, but GETs work. What is going on?

Answer it in your own words first, then compare.

2. How do you publish a RAP OData V4 service and make it usable for a Fiori app and an integration?

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