on 2025 Oct 09 7:02 PM
<EQUIP_NO>, <EQUIP_NO_PADDED> (18-char with leading zeros), <FUNC_LOC>, <SHORT_TEXT>, <LONG_TEXT>. You’ll still need a bit of local effort to wire transports, authorizations, CSRF handling, and adjust BAPI structures in your own system.When I first had to expose SAP Plant Maintenance notifications as an API, I wasn’t an ABAP developer. I live in the world of APIs, Node.js, and microservices — not in SE80 or BAPIs. Still, with a little help from AI, I built a working SAP OData service that creates and retrieves PM notifications using the classic BAPI_ALM_NOTIF_CREATE.
This post is my path from “what’s a BAPI?” to a fully functioning OData endpoint that anyone can call from Postman or a modern front-end app.
We needed an API to create maintenance notifications (equipment breakdowns, inspection reports, etc.) from an external system into SAP.
SAP does ship a standard service (/sap/opu/odata/sap/API_MAINTNOTIFICATION), but it wasn’t enough. We needed custom validations, long text handling, and our own response messages. So I decided to build a custom OData service:
/sap/opu/odata/sap/ZSERVICE_PM_NOTIFICATION_SRVThe only problem? I’m not an ABAPer.
I asked ChatGPT (my ABAP copilot):
“Generate an OData service to create a Maintenance Notification with Equipment, FunctLoc, ShortText, and LongText.”
It gave me the SEGW model and even named the right BAPI (BAPI_ALM_NOTIF_CREATE). In SEGW, I created the project and an entity Notification like this:
Field Type Description
MaintenanceNotification | Edm.String(12) Key | Notification No |
Equipment | Edm.String(18) | Equipment No |
FunctLoc | Edm.String(30) | Functional Location |
ShortText | Edm.String(40) | Problem Description |
LongText | Edm.String(1024) | Additional Notes |
Message | Edm.String(255) | Response Message |
Then I generated runtime artifacts → MPC, DPC, and DPC_EXT classes. So far, no manual code.
CREATE_ENTITY LogicThe AI produced a clean version I pasted intoZCL_ZPM_NOTIF_DPC_EXT → NOTIFICATIONSET_CREATE_ENTITY.
METHOD notificationset_create_entity.
DATA: ls_in TYPE zcl_zpm_notif_mpc=>ts_notif,
ls_out TYPE zcl_zpm_notif_mpc=>ts_notif,
ls_hdr TYPE bapi2080_nothdri,
lt_return TYPE STANDARD TABLE OF bapiret2,
ls_return TYPE bapiret2,
lv_notif TYPE qmnum,
lv_notif_c TYPE char12.
" Read payload from POST JSON
io_data_provider->read_entry_data( IMPORTING es_data = ls_in ).
IF ls_in-shorttext IS INITIAL.
RAISE EXCEPTION TYPE /iwbep/cx_mgw_busi_exception
EXPORTING message = 'ShortText is required'.
ENDIF.
" Optional but recommended: pad equipment to 18 (ALPHA)
IF ls_in-equipment IS NOT INITIAL.
DATA(lv_equ) = ls_in-equipment.
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING input = lv_equ
IMPORTING output = lv_equ.
ls_hdr-equipment = lv_equ.
ENDIF.
" Map input to BAPI header
ls_hdr-descript = ls_in-shorttext.
ls_hdr-funct_loc = ls_in-functloc.
IF ls_hdr-equipment IS INITIAL.
ls_hdr-equipment = ls_in-equipment.
ENDIF.
" Call BAPI to create the notification
CALL FUNCTION 'BAPI_ALM_NOTIF_CREATE'
EXPORTING
notif_type = 'M1'
notifheader = ls_hdr
IMPORTING
number = lv_notif
TABLES
return = lt_return.
" Save and commit the notification
CALL FUNCTION 'BAPI_ALM_NOTIF_SAVE'
EXPORTING number = lv_notif
TABLES return = lt_return.
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
EXPORTING wait = abap_true.
" Format notification number
lv_notif_c = |{ lv_notif ALPHA = OUT }|.
" Prepare OData response
ls_out-maintenancenotification = lv_notif_c.
ls_out-equipment = ls_in-equipment.
ls_out-functloc = ls_in-functloc.
ls_out-shorttext = ls_in-shorttext.
ls_out-longtext = ls_in-longtext.
ls_out-message = |Created notification { lv_notif_c }|.
er_entity = ls_out.
ENDMETHOD.Even though AI wrote the ABAP, I learned:
io_data_provider maps JSON → ABAP structure.er_entity sends back the OData response.BAPI_ALM_NOTIF_CREATE creates the record; BAPI_ALM_NOTIF_SAVE + COMMIT persists it.In /IWFND/GW_CLIENT, I ran:
POST /sap/opu/odata/sap/ZSERVICE_PM_NOTIFICATION_SRV/NotificationSet{
"Equipment": "<EQUIP_NO>",
"FunctLoc": "<FUNC_LOC>",
"ShortText": "<SHORT_TEXT>",
"LongText": "<LONG_TEXT>"
}{
"d": {
"MaintenanceNotification": "100012345678",
"Equipment": "<EQUIP_NO>",
"FunctLoc": "<FUNC_LOC>",
"ShortText": "<SHORT_TEXT>",
"Message": "Created notification 100012345678"
}
}That was the moment — the notification number finally showed up 🎉.
To list notifications, AI suggested BAPI_ALM_NOTIF_GETLIST. Minimal example:
METHOD notificationset_get_entityset.
DATA: lt_notif TYPE TABLE OF bapi2080_notif_list,
ls_notif TYPE bapi2080_notif_list.
CALL FUNCTION 'BAPI_ALM_NOTIF_GETLIST'
EXPORTING notif_type = 'M1'
TABLES notiflist = lt_notif.
LOOP AT lt_notif INTO ls_notif.
APPEND VALUE zcl_zpm_notif_mpc=>ts_notif(
maintenancenotification = ls_notif-notif_no
shorttext = ls_notif-descript
functloc = ls_notif-funct_loc
equipment = ls_notif-equipment
) TO et_entityset.
ENDLOOP.
ENDMETHOD.Now I can hit:
GET /sap/opu/odata/sap/ZSERVICE_PM_NOTIFICATION_SRV/NotificationSet…and get a clean JSON list of maintenance notifications.
When the notification number didn’t return, AI helped me debug like this:
ZCL_ZPM_NOTIF_DPC_EXT./IWFND/GW_CLIENT → POST again to hit the breakpoint.ls_hdr-descript, ls_hdr-equipment, lv_notif, ls_out-maintenancenotification./IWBEP/ERROR_LOG (Gateway errors)/IWFND/TRACES (payload/trace)ST22 (ABAP dumps)Common fixes
CONVERSION_EXIT_ALPHA_INPUT before calling the BAPI.M1/M2 as per your config.Lesson Explanation
| BAPI ≈ SAP’s internal API | Think of BAPI_ALM_NOTIF_CREATE as a function that writes a record. |
| ALPHA = OUT | Formats numbers with leading zeros for display (e.g., 1234 → 000000001234). |
| DPC_EXT | Where you write logic; like a controller in Node.js. |
er_entity = ls_out | Your OData response back to the caller. |
/IWFND/GW_CLIENT | SAP’s built-in Postman! |
If your payload has long descriptions, add a helper:
IF ls_in-longtext IS NOT INITIAL.
me->add_qmel_longtext(
iv_notifno = lv_notif_c,
iv_longtxt = CONV string( ls_in-longtext )
).
ENDIF.This will save long text into SAP’s long-text tab automatically (implement your helper with SAVE_TEXT).
Use this when something fails. Replace placeholders with your values.
Prompt:
You are an SAP Gateway & PM ABAP/OData debugger. I have an OData service that creates PM Notifications. Analyze and give exact fix steps with code diffs.
Context
- System/SID/Client: <SID>/<CLIENT>
- Endpoint: <HOST>/sap/opu/odata/sap/ZSERVICE_PM_NOTIFICATION_SRV/NotificationSet (or V4 path)
- Action: POST create notification
- Error (verbatim): "<ERROR_TEXT>"
- /IWBEP/ERROR_LOG ID: <LOG_ID> (stack excerpt below)
- Payload JSON: { "Equipment": "<EQUIP_NO>", "FunctLoc": "<FUNC_LOC>", "ShortText": "<SHORT_TEXT>", "LongText": "<LONG_TEXT>" }
- Code snippet(s): DPC_EXT create_entity + NOTIFICATIONSET_CREATE_ENTITY
- BAPI flow: BAPI_ALM_NOTIF_CREATE → BAPI_ALM_NOTIF_SAVE → BAPI_TRANSACTION_COMMIT
Please verify
1) Equipment padding (ALPHA to 18 chars) and existence in EQUI/EQKT; try <EQUIP_NO_PADDED>.
2) Correct notif_type (M1/M2) and header mapping (funct_loc, equipment, short_text).
3) CSRF token and Content-Type; provide exact curl/Postman sequence if wrong.
4) Authorization/object checks for plant and notification type.
5) Number ranges if equipment creation fails (SNRO: EQUIP_NR, OIEN assignment).
6) Gateway exception mapping to /iwbep/cx_mgw_busi_exception messages.
7) If RAP/CDS path is used, handler create logic and service binding.
Artifacts
- ERROR_LOG excerpt: <PASTE_LOG>
- Code snippet: <PASTE_DPC_EXT_METHOD>
Deliver a concise fix with the exact ABAP line(s)/payload to change.ZSERVICE_PM_NOTIFICATION_SRVYou don’t have to be an ABAP veteran to build SAP OData services. With AI assistance, patience, and a few SAP debugging tools, even integration engineers can craft end-to-end APIs that interact directly with the core system.
Author: Sayantan Tarafdar
Title: How I Used AI to Build an SAP PM Notification OData API (as a Non-ABAP Developer)
Tags: #SAPBTP #OData #BAPI_ALM_NOTIF_CREATE #PlantMaintenance #Integration #ABAPForNonABAPers
Request clarification before answering.
This was such a refreshing read, I love seeing someone outside the traditional ABAP crowd get hands-on and actually build from scratch something that we all underdstand and that eventually works. The clarity and honesty in your walkthrough make this piece genuinely empowering, it opens doors that some people would rather keep closed. Don’t let the gatekeepers discourage you, innovation often comes from people who aren’t told “that’s not how we do it.” Please keep writing posts like this; they bridge a huge gap between integration devs and the SAP core world.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I'm not seeing a confirmation this whole thing actually works. The long text part is only vaguely explained as "optional" and no code is shared, so it's impossible to tell.
There is a problem with BAPI RETURN table not evaluated for errors. Even if this doesn't work, the code as written will always return a "success" type message. So yeah, it "works". Until it doesn't.
So, uh... hi! Welcome to SAP Community! I'm guessing you meant to post this as a blog post and not as a question. I'm not surprised though: I've been using this website for decades and in its current form even I have no idea how to do anything here. You could probably copy-paste it as a blog post, but this post already got mentioned on LinkedIn, so it would be a shame to lose the link. As a side note, lack of reaction here is also due to the fact that (a) this was (mistakenly?) posted as Q&A and (b) not mentioning the popular ABAP Development tag that some people use in RSS feeds to rack any new content.
Anyways. Please don't take this as a criticism in your address. I think this is a great post and opens a much needed discussion. But the reality is: the solution here, the code and everything - it's just... uh... not great. And again, it's not your fault because you have no way of knowing when AI gives bad advice.
What you got is most likely what I would get if I went on to "vibe code" something in a language I have no idea about. And that's exactly the problem. We shouldn't just blindly trust AI-generated stuff and "ship it" to Production. I sincerely hope this... creation didn't actually go live in a productive SAP system. There should always be some oversight (like a peer code review), otherwise we're going to have a bad time, as humanity.
I'm not going to go through item by item and list all the problems with what you ended up with. Again, not to criticize you personally but that would be quite a long list. I just wanted to comment here to note what I think are bigger problems.
1. Why doesn't SAP API have more functionality? What is mentioned here seems reasonable to me. Why isn't it just delivered by SAP?
2. Why were you put in the situation where you had to create an API yourself without having necessary skills? If you're just doing this as a hobby, it's fine. But if it's intended for productive use, why do you even need to do this all by yourself? There is no shortage of ABAP developers. So, what gives? This sounds suspiciously like yet another dumb management-driven initiative and we all know how well those end.
I'm glad you're exploring ABAP and AI tools, this is commendable. But the result is not a happy Cinderella story that it may appear to be. It's rather a cautionary tale of Little Red Riding Hood. And I'm afraid too many people won't know the difference.
Thank you for sharing!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
| User | Count |
|---|---|
| 6 | |
| 5 | |
| 3 | |
| 2 | |
| 2 | |
| 1 | |
| 1 | |
| 1 | |
| 1 | |
| 1 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.