Service Definitions
RAP / CDS / ODataadvanced

Service Definitions Part 5: UI vs Integration APIs — Reuse or Separate?

Key takeaway

Decide whether a Fiori app and an integration API should share one service or have separate ones, and how to structure projections, BDEFs, services and bindings for each.

Explanation

📌 KEY POINTS
✅ Same business object, different consumers → separate projections and service definitions.

✅ UI service: draft, UI annotations, value helps, side effects; binding "OData V4 – UI".

✅ API service: no draft, stable contract, only needed operations; binding "OData V4 – Web API".

⚠️ Sharing one service couples UI changes to integration contracts.

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

Parts 1–4 focused on one service. Real BOs usually have at least two consumers: a Fiori app and an integration. This part explains why they get separate services.

━━━━━━━━━━━━━━━━━━━━
▶ 1. HOW THE CONSUMERS DIFFER

Fiori app:

  • Users edit over time → draft.
  • Needs UI annotations, value helps, text fields, side effects.
  • Changes often with UX feedback.

Integration API:

  • Systems send complete requests → no draft.
  • Needs a stable contract, clear errors, only required operations.
  • Changes rarely and only compatibly.

━━━━━━━━━━━━━━━━━━━━
▶ 2. THE STRUCTURE

One base BO (ZR_PurchReq) with all behavior. Then per consumer:

  • UI: ZC_PurchReq (+ projection BDEF with "use draft"), metadata extension, service ZUI_PURCHREQ, binding ZUI_PURCHREQ_O4 (OData V4 – UI).
  • API: ZA_PurchReq (+ projection BDEF without draft, only create/update/approve), service ZAPI_PURCHREQ, binding ZAPI_PURCHREQ_O4 (OData V4 – Web API).

Business logic stays in one place; each consumer gets its own contract.

━━━━━━━━━━━━━━━━━━━━
▶ 3. WHY NOT SHARE?

  • Draft in an API makes clients handle draft actions — unnecessary complexity.
  • UI-driven field additions or label changes would alter the API contract.
  • Different authorization needs (communication users vs dialog users).
  • Different release cycles.

━━━━━━━━━━━━━━━━━━━━
▶ 4. WHEN SHARING IS ACCEPTABLE

Small internal read-only services used by one app and one internal report may share — if both are owned by the same team and change together. Default to separation.

━━━━━━━━━━━━━━━━━━━━
▶ 5. WEB API SPECIFICS

  • Web API bindings do not deliver UI annotations and are meant for system-to-system use; expose them via communication scenarios/arrangements for technical users in cloud systems (or appropriate roles on-premise).
  • Document the API (entity sets, actions, errors) for consumers.

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

  1. Keep the base BO unchanged.
  2. Create ZA_ projections and a projection BDEF without draft (code example).
  3. Create ZAPI_PURCHREQ and bind it as OData V4 – Web API.
  4. Test with an HTTP client: create a request with items in one call, approve it.

✅ CHECKPOINT: each consumer has its own contract on the same business logic.

Code example

ABAP Code
// ===== API projection (no draft, API-friendly) =====@EndUserText.label: 'Purchase Request - API'@AccessControl.authorizationCheck: #CHECKdefine root view entity ZA_PurchReq  provider contract transactional_query  as projection on ZR_PurchReq{  key RequestUUID,      RequestID,      Description,      Supplier,      Status,      TotalAmount,      CurrencyCode,      _Item : redirected to composition child ZA_PurchReqItem} // ===== API projection BDEF: only what integrations need =====projection;strict ( 2 );// no "use draft" -> no draft for API clientsdefine behavior for ZA_PurchReq alias PurchaseRequest{  use create;  use update;  use action approve;  use association _Item { create; }}define behavior for ZA_PurchReqItem alias PurchaseRequestItem{  use update;  use delete;  use association _Request;} // ===== Two services on one BO =====define service ZAPI_PURCHREQ {                     // bound as OData V4 - Web API  expose ZA_PurchReq     as PurchaseRequest;  expose ZA_PurchReqItem as PurchaseRequestItem;}// ZUI_PURCHREQ (ZC_ projections, use draft)       // bound as OData V4 - UI // ===== API test: deep create in one call =====// POST .../zapi_purchreq/0001/PurchaseRequest// { "Description": "Laptops", "CurrencyCode": "EUR",//   "_Item": [ { "ItemNo": "0010", "Quantity": 3, "Price": 1200 } ] }

Real project scenario

A company exposed its Fiori UI service (with draft) to an external procurement tool. The tool's developers had to implement Edit, Prepare and Activate calls, and every UI release that added a field broke their mapping.
The team created a separate Web API service without draft on the same BO, with only create, update and approve. The external tool switched to it, its integration code shrank by half, and UI changes no longer affected the partner.

Common mistakes

  • Exposing the UI service with draft to integrations.
  • Reusing UI projections for APIs.
  • Exposing all operations to APIs "for flexibility".
  • Duplicating business logic in API-specific code instead of reusing the BO.
  • Binding an API as OData V4 – UI.

Best practices

  • One base BO, separate projections, service definitions and bindings per consumer.
  • UI with draft and annotations; API without draft, minimal and stable.
  • Web API binding for system integration, with technical users.
  • Document API contracts and version breaking changes.
  • Test APIs with deep create and error cases.

Interview angle

Questions: "Should a Fiori app and an integration use the same service?", "How do you structure a RAP BO for UI and API?"
Strong answer: separate them: same base BO, but separate projections (UI with draft and annotations, API without draft and with minimal operations), separate service definitions and bindings (V4 UI vs V4 Web API). Reasons: draft complexity for clients, contract stability, authorization and release cycles differ. Business logic remains in the base BO.

Practice this lesson

Quick check

1. A batch integration reuses a draft-enabled Fiori service and keeps failing on draft actions. What is the best fix?

2. One service is shared by an internal UI and a partner integration. UI changes keep breaking the partner. What should the team do?

3. Which binding type fits a system-to-system integration using a RAP service?

Interview questions

1. Should a Fiori app and an external integration share one RAP service? Explain your design.

Answer it in your own words first, then compare.

2. You inherit several RAP services. What do you review in their service definitions?

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