Ajax lets you refresh part of the page without a full reload, which makes your app feel faster. In Oracle APEX, the simplest, most reliable way to do this is with apex.server.process. In this tutorial, you will set up an Ajax Callback on the server, call it from JavaScript, pass values, get a response, handle errors, and wire it into a Dynamic Action. I will also share a few best practices I use on real projects.
What is apex.server.process?
apex.server.process is a JavaScript function that calls a server-side APEX process by name. You can send page item values, custom parameters, and expect a response as text or JSON. The basic syntax is:
apex.server.process(pName, pData, pOptions)
pName: the name of your Ajax Callback process.pData: what to send, likepageItemsorx01tox10.pOptions: options likedataType, and callbacks for success or error.
Example 1: Get the Text Response using Ajax Callback in APEX
The following example demonstrates how to create an Ajax callback in an Oracle APEX page and invoke it on a button click to display the entered value in a page item through a success message.
Step 1: Create an Ajax Callback process in APEX
In Page Designer:
- Go to the Processing tab, right-click on Ajax Callback, and create a new process.
- Name it, for example, GREET_USER.
- In the PL/SQL Code area, return something via
htp.porapex_json.
Example code that returns the value of page item P1_NAME (you can change the item name according to your page item):
BEGIN
htp.p('Hello ' || :P1_NAME);
END;
Note: the name, here GREET_USER, must match the first argument in your JavaScript call.
Step 2: Trigger the Ajax call from JavaScript
Create a Button, add a Dynamic Action on Click, True Action: Execute JavaScript Code. Paste the following apex.server.process call there.
JavaScript:
apex.server.process(
"GREET_USER",
{ pageItems: "#P1_NAME" },
{
dataType: "text"
}
).done(function (msg) {
apex.message.clearErrors();
apex.message.showPageSuccess(msg);
}).fail(function (jqXHR, textStatus, errorThrown) {
apex.message.alert("Error: " + textStatus + ", " + errorThrown);
});
Now save the changes and run the page. Input any name into it and click on the button. You will get the output something like below:

What to notice:
"GREET_USER": matches the Ajax Callback process name.pageItems: "#P1_NAME": sends P1_NAME to the session state before the call, then your PL/SQL can read:P1_NAME. If you need multiple items, separate with commas, for example"#P1_A,#P1_B".dataType: "text": tells APEX you expect plain text..done(function (msg) { ... }): runs on success. Here we show a page success message..fail(function (...) { ... }): catches errors, which is vital for debugging.
Example 2: Return JSON and set items using Ajax Callback in Oracle APEX
Create a new Ajax Callback process
- Go to the Processing tab, right-click on Ajax Callback, and create a new process.
- Name: GET_EMP.
PL/SQL Code that returns JSON with apex_json:
DECLARE
l_emp employees%ROWTYPE;
BEGIN
SELECT * INTO l_emp FROM employees
WHERE employee_id = TO_NUMBER(:P1_EMP_ID);
apex_json.open_object;
apex_json.write('name', l_emp.first_name || ' ' || l_emp.last_name);
apex_json.write('email', l_emp.email);
apex_json.write('salary', l_emp.salary);
apex_json.close_object;
END;
Add page items
- P1_EMP_ID, Text Field.
- P1_NAME, P1_EMAIL, P1_SALARY, Display Only or Text Field.
Create a button, for example BTN_FETCH. Add a Dynamic Action on Click.
JavaScript:
apex.server.process(
"GET_EMP",
{ pageItems: "#P1_EMP_ID" },
{ dataType: "json" }
).done(function (data) {
$s("P1_NAME", data.name);
$s("P1_EMAIL", data.email);
$s("P1_SALARY", data.salary);
}).fail(function (jqXHR) {
apex.message.alert("Could not fetch employee. " + jqXHR.responseText);
});
Key points:
dataType: "json": now the response is parsed into a JavaScript object.$s("ITEM", value): sets an APEX item value.- If you forget
dataType: "json", you will get a string, not an object.
Output:

Example 3: Send custom parameters with x01 to x10 using Ajax Callback in APEX
When you do not want to write page items to the session state, send values as x01 to x10. Read them in PL/SQL via apex_application.g_x01, and so on.
Create a new Ajax Callback process (using the same steps as above)
- Name: SAVE_PREFS.
Add page items
- P1_THEME, Select List or Text Field.
- P1_ROWS, Number Field.
Ajax Callback Process PL/SQL Code: SAVE_PREFS
DECLARE
l_theme VARCHAR2(100) := apex_application.g_x01;
l_rows NUMBER := TO_NUMBER(apex_application.g_x02);
BEGIN
-- Save preferences, for example into a table
apex_json.open_object;
apex_json.write('status', 'ok');
apex_json.close_object;
END;
Create a Save button. Add a Dynamic Action on Click, True Action: Execute JavaScript Code that calls the following process. No Set Value is needed, values are read directly from the items in the browser.
JavaScript:
apex.server.process(
"SAVE_PREFS",
{
x01: $v("P1_THEME"),
x02: $v("P1_ROWS")
},
{ dataType: "json" }
).done(function (resp) {
if (resp.status === "ok") {
apex.message.showPageSuccess("Preferences saved");
} else {
apex.message.alert("Could not save preferences");
}
});
Why this is useful:
- No need to create hidden items just to pass values.
- Parameters stay transient, good for quick filters or settings.
Common options and tips
- Show a spinner during long calls:
var sp = apex.util.showSpinner( apex.jQuery("body") );
apex.server.process("LONG_TASK", {}, { dataType: "text" })
.always(function(){ sp.remove(); });- Debug server errors: check the browser console Network tab, look at Response. On the server, add logging or
apex_debug.message. - Keep names consistent: the process name in JavaScript must match the Ajax Callback name exactly.
- Choose the right transport:
- Use
pageItemswhen you want the session state updated. - Use
x01tox10for quick parameters without session state.
- Use
Closing
You now know how to create an Ajax Callback, call it with apex.server.process, pass data with pageItems or x01 to x10, receive text or JSON, and handle success or errors. Start with the basic text example, then move to JSON once you are comfortable. In my apps, I use JSON for most calls; it is cleaner and easier to expand later.



