REST APIs in PL/SQL: Unleashing Oracle with ORDS
You don't need a heavy Node.js or Java Spring Boot middle-tier to build APIs. Learn how Oracle REST Data Services (ORDS) seamlessly bridges the gap between HTTP JSON requests and native PL/SQL logic.
What is ORDS?
Oracle REST Data Services (ORDS) is a mid-tier Java application that connects to your Oracle Database. It maps HTTP URLs and verbs (GET, POST, PUT, DELETE) directly to database transactions.
Instead of writing a Node.js server that opens JDBC connections, executes queries, parses results into JSON, and returns them, you simply write PL/SQL. ORDS handles all the JSON serialization and HTTP protocol overhead for you automatically.
Auto-REST Enabling Tables
The absolute fastest way to build an API is Auto-REST. If you have an EMPLOYEES table, you can generate full CRUD (Create, Read, Update, Delete) APIs against it with a single PL/SQL call.
Immediately, the following endpoints are live:
GET /ords/hr/emps/(Returns all rows in JSON, with built-in pagination!)GET /ords/hr/emps/101(Returns employee 101)POST /ords/hr/emps/(Inserts a new employee from a JSON body)
Building Custom PL/SQL Endpoints
Auto-REST is great, but usually, you want to expose complex business logic, not just raw tables. For this, we build custom endpoints.
Step 1: Define the Module and Template
Step 2: Define the Handler (The PL/SQL Logic)
We attach a GET handler to our template. ORDS automatically converts any SYS_REFCURSOR into a perfectly formatted JSON array.
If a user hits GET /api/inventory/check/12345, ORDS passes 12345 into the :item bind variable, executes the SQL, and returns:
{"items": [{"loc": 100, "stock_on_hand": 50}, {"loc": 200, "stock_on_hand": 10}]}
Handling URI Parameters
In the example above, :item in the URI automatically bound to :item in the PL/SQL.
For POST requests, if the client sends a JSON body like {"status": "ACTIVE"}, you can access it in your PL/SQL handler by simply referencing the bind variable :status! ORDS parses the incoming JSON body automatically.
Securing APIs with OAuth 2.0
Never leave your endpoints completely open. ORDS includes a built-in OAuth 2.0 authorization server.
- Create a Privilege: Group your modules under a privilege.
- Create a Client App: Generate a
Client IDandClient Secretfor your third-party consumer. - Grant Access: Assign the privilege to the Client App.
The consumer must first POST their ID and Secret to the /oauth/token endpoint to receive a short-lived Bearer Token. They must pass this token in the Authorization header of subsequent API calls.
Common Gotchas
Important Gotchas
- !
If your PL/SQL handler throws an unhandled exception (like
NO_DATA_FOUND), ORDS will generically return anHTTP 500 Internal Server Error. If you want to return a specificHTTP 404 Not Found, you must explicitly set the status code using:status_code := 404;in your exception block. - !
If you need to access specific HTTP headers (like a custom
X-Forwarded-For), you must map them explicitly usingORDS.DEFINE_PARAMETERbefore they become available as bind variables in your PL/SQL block.
Key Takeaways
Key Takeaways
- ORDS eliminates the need for middle-tier applications when exposing database logic as APIs.
- Use Auto-REST for instant CRUD endpoints on raw tables and views.
- Use Modules, Templates, and Handlers to execute complex PL/SQL business logic behind REST URIs.
- Secure your endpoints using the built-in OAuth 2.0 token workflows.


