Search This Blog

Tuesday, June 9, 2026

Building an AI-Driven Oracle Fusion Cloud Analysis Tool: What We Learned Along the Way

If you work with Oracle Fusion Cloud and have ever felt like you need more insights when it comes to data quality, process health, or IDR performance, you are not alone. The Oracle ecosystem is rich, but the gap between "we have the data" and "we actually understand what the data is telling us" can be enormous. This post walks through how we built a Python-based analysis pipeline called Catalyst AI Lab that connects directly to Oracle Fusion Cloud REST APIs and surfaces actionable findings automatically, and how AI-assisted development made the whole thing possible in a fraction of the time it would have taken otherwise.

The Problem Worth Solving

Our team supports Oracle Fusion Cloud across ERP, EPM and HCM. Like most teams, we spent a lot of time answering the same questions: Why is our Straight-Through Processing rate lower than expected? Are there duplicate suppliers in the system? Which business units have the most unresolved invoice holds, and how old are those holds? Among many other existential questions!

The answers exist in Oracle. The REST APIs are well-documented enough to get started. But building something repeatable and systematic that could answer these questions reliably, across environments, and produce a report someone could actually act on -- that is a different project entirely.

The goal was to build a tool that behaves like a knowledgeable consultant running a discovery engagement: it goes into the system, looks at the data from multiple angles, identifies what is worth paying attention to, and tells you why it matters.

The Architecture: Discovery Lenses

We organized the analysis into what I call discovery lenses. Each lens is a focused analytical perspective that targets a specific domain. The IDR Invoice Processing lens, for example, looks at STP rates, hold root causes, duplicate invoices, supplier-level IDR success, and per-BU performance breakdowns. The Supplier Data Quality lens looks at the entire supplier master for duplicates, missing site attributes, banking configuration gaps, tax registration coverage, and cross-BU payment term consistency.

Each lens follows the same pattern: connect to Oracle, fetch the relevant data via REST API, run analysis, produce structured findings with severity levels, confidence scores, and remediation guidance, then export everything to an HTML report and supporting CSV files for drill-down in Excel.

The framework is extensible. Adding a new lens means creating one Python file, decorating a class with @register_lens, and adding configuration to a YAML file. No changes to the core pipeline needed.

Agentic Development: What It Actually Looks Like

I want to be honest about what AI-assisted development meant on this project, because there is a lot of noise around this topic.

The GitHub Copilot agent in VS Code was not just writing boilerplate. I was having extended conversations with it about Oracle API behavior, asking it to review findings for accuracy, having it run the pipeline against our dev environment and then analyze the results, and using it to write and fix tests. When a finding was surfaced with a remediation recommendation that turned out to be wrong (more on that below), we flagged it, the agent researched the correct Oracle Cloud guidance, and we updated both the code and the best practices configuration together.

The workflow looked like this: I would describe what I wanted to understand about the data. The agent would research the Oracle REST API structure, write the lens code, run the pipeline, and report back with results. Then we would review the output together, identify what was accurate, what was misleading, and what needed more nuance. That iterative loop is where the real value was. It compressed weeks of work into days.

The test suite ended up at 632 tests covering pagination behavior, finding logic, report generation, CLI commands, and end-to-end pipeline execution. Having the agent write those tests alongside the features meant I could refactor confidently.

Oracle REST API: Things You Will Not Find in the Quick Start

This is the section I wish existed when we started.

First, pagination. Oracle Fusion Cloud REST APIs use offset/limit pagination with a default page size of 100 records. That is straightforward. What is not obvious is that if you want Oracle to tell you how many total records exist, you have to explicitly pass totalResults=true as a query parameter on your request. Without it, the API returns your page of data but gives you no indication of the overall population size. We were calculating STP rates against a 20,000-invoice sample before realizing we had 275,180 invoices YTD. That is a 7.3% sample, which changes how you interpret the findings significantly.

The fix was simple once we understood it: on the first page request, add totalResults=true to the query string. Oracle then returns the estimated row count in the response, and you can surface that alongside your findings as a population coverage metric. Every finding now shows something like "analyzed 20,000 of 275,180 invoices (7.3% coverage)" so the reader understands the confidence level of what they are seeing.

Second, filter syntax on certain resources. Oracle's REST API supports query filters using a SCQL-style syntax, which is powerful for many resources. But for invoiceHolds specifically, we discovered that compound filters with semicolons are silently ignored. You cannot filter by multiple conditions in a single request on that resource. The API accepts the request without error, applies no filter at all, and returns unfiltered data. If you are not paying attention, you will think your filter worked and analyze the wrong dataset. The workaround is to fetch the broader dataset and filter in application code.

Third, the OpenAPI specification files for Oracle Fusion Cloud are enormous. The five files covering ERP Financials, PPM, Procurement, Common, and HCM total nearly 400MB. You cannot parse those with standard JSON libraries without running into memory issues. The solution was ijson, a streaming JSON parser that lets you walk through the spec without loading it all into memory at once.

Fourth, credentials. Oracle Cloud API credentials need to be stored securely. The pipeline uses OS keyring integration (Windows Credential Manager on Windows, Keychain on Mac) so passwords are never in plain text files, never in environment variables that might get logged, and never in source control. This is worth doing properly from the start because once you have multiple environments and multiple team members, credential hygiene matters.

What the Analysis Actually Found

Running the full pipeline against our Prod clone environment produced some results worth highlighting, both because they illustrate what this kind of tool can surface and because they validate the approach. Below are a couple of material examples.

On the IDR side: our overall STP rate looked reasonable at the summary level, but the per-BU breakdown showed significant variance. Several business units were well below the industry benchmark. That variance was invisible in aggregate reporting. The hold analysis showed issues, which is a cash flow concern that should have been caught in normal operations.

On the supplier side: analyzing all suppliers at 100% population coverage found many potential duplicate supplier groups, duplicate addresses, and active suppliers flagged as Do Not Use. The real value is that the tool gives you a prioritized, evidence-backed list to work through rather than asking someone to manually review a spreadsheet with thousands of rows.


Click on the image to expand it~

Lessons on Accuracy and Iteration

One thing I want to be direct about: the first version of several remediation recommendations in the tool were wrong. Not wrong in a subtle way -- wrong in the sense that they referenced Oracle lookup values that do not exist in standard Cloud instances, or recommended configuration changes that would break other functionality.

This happened because the AI was drawing on general Oracle knowledge that did not perfectly match Oracle Cloud specifically. The fix was systematic: review every finding's remediation guidance against actual Oracle Cloud documentation and lived experience, update the best practices configuration file that drives the recommendations, and add tests that assert the correct guidance is present.

That iteration process is not a failure of AI-assisted development. It is how the process is supposed to work. The agent accelerates construction; human expertise and domain knowledge ensure correctness. If you skip the review step, you will ship wrong recommendations at scale. If you do the review, you end up with something accurate and fast.

How You Can Apply This to Your Environment

The pattern generalizes beyond the specific lenses we built. If you support Oracle Fusion Cloud in any capacity, you almost certainly have questions you are answering manually today that could be answered systematically with this approach.

Start with one question you care about. What is your PO-backed invoice percentage? How many suppliers have incomplete site setup? What is the distribution of expense report approval times across business units? Pick something with a clear Oracle REST API resource behind it, build a focused analysis around it, validate the results against what you know to be true, and iterate from there.

The Oracle REST API surface area is large enough that you can build meaningful analytics across almost any domain without needing a data warehouse, a separate reporting tool, or an extract from production. The data is there. The APIs are there. The AI tooling to help you build something coherent on top of them is better than it has ever been.

The repository for this project is internal to our organization, but the patterns, the Oracle API gotchas, and the architectural approach are all things you can apply independently. If you are working on something similar or have questions about the Oracle-specific pieces, drop a comment below. I am happy to go deeper on any of it.

How I Built an Oracle AI-Driven Support Tool for Oracle Cloud Using Databricks, OCI and Claude

If you've spent any time supporting Oracle Cloud ERP, HCM, or EPM, you already know the pattern. A user submits a ticket about a payroll element not processing. You ask a series of diagnostic questions. You identify whether it's an effective date problem, a payroll cutoff issue, a security profile gap, or one of a dozen other root causes. You document the fix. Two months later, a different user hits the same issue and the whole cycle starts over.

This post walks through a tool I built to break that cycle. It is called Solution Designer, and it uses an agentic AI approach on top of Databricks to give your Oracle support team structured, consistent, context-aware troubleshooting guidance -- without requiring users to know exactly what to ask.

The Problem With Generic AI for Oracle Support

The first instinct most teams have is to point users at a general-purpose chatbot. "Just ask it your Oracle question." The problem is that Oracle Cloud is enormous and deeply configuration-dependent. A question like "why isn't my payroll processing?" has radically different answers depending on element type, entry method, effective date, pay period status, and whether payroll has already been run for the period.

A generic chat interface puts all of that burden on the user. They have to know which details matter, phrase the question precisely, and interpret an answer that wasn't tuned to their specific setup.

I took a different approach. Instead of a free-form chat interface, I built a guided intake flow that collects the right diagnostic signals before the AI ever generates a response. The model then has full context to produce a solution that actually fits the situation.

What Solution Designer Does

At its core, the tool is a Flask application deployed as a Databricks App. It connects to OCI or Claude via the Databricks Foundation Model API or the OCI LLM API. The experience works like this:

1. The user picks a scenario from a categorized library. The library currently covers 31 Oracle scenarios across ERP (Payables, Procurement, Receivables, General Ledger, Fixed Assets, Inventory, Projects), HCM (Payroll, Absence, HCM Data Loader, Fast Formula, Security, Workforce Compensation), EPM (Consolidation, Planning Data Loads, Rule Troubleshooting), and integrations (REST API, FBDI, BI Publisher, OTBI, Workflow Notifications).

2. The tool presents a structured intake form specific to that scenario. For Payroll Element Entries, for example, the user answers eight targeted questions: what type of element, how it was created, the specific symptom, how many employees are affected, the effective date, the pay period, whether payroll has already run, and the current status of the element entry. Every question has help text explaining why it matters.

3. The scenario definition includes edge cases. Each scenario JSON file encodes known Oracle gotchas as conditional logic. If the effective date falls outside the pay period, the system flags that as a high-severity edge case and incorporates it into the prompt context automatically. If payroll already ran and the entry is still unprocessed, the tool knows to surface the rollback-or-next-period decision. Users do not have to discover these traps manually.

4. OCI or Claude generates a tailored solution. With the structured inputs and edge case context loaded, OCI/Claude produces a step-by-step resolution path that is specific to what the user actually described. This is not a generic knowledge article. It is a direct answer to their exact configuration.

5. The user can refine through follow-up questions. After the initial solution, the conversation stays open. Users can ask clarifying questions and the system maintains full session context so responses stay coherent. Sessions persist in a Unity Catalog Delta table so the conversation survives page refreshes and can be resumed later.

6. After rating the solution, the user can generate a training document. Once the problem is solved and the user rates the response, a "Generate Training Doc" button appears. They specify a format (Markdown, slide outline, or quick-start guide) and a target audience, and OCI/Claude turns the solution into a shareable knowledge artifact. This is where individual troubleshooting events compound into reusable organizational knowledge.

How the Knowledge Base Works

Each scenario is a JSON file that defines intake questions, answer options, help text, edge cases, and the conditions that trigger them. Here is a simplified example from the Payroll Element Entries scenario:

```json

{

  "id": "oracle-hcm-payroll-element-entries",

  "category": "Oracle HCM",

  "title": "Payroll Element Entries Not Processing",

  "intake_questions": [

    {

      "id": "effective_date",

      "question": "What is the effective date of the entry?",

      "type": "text",

      "required": true,

      "help_text": "Enter date in format MM/DD/YYYY - must be within pay period"

    }

  ],

  "edge_cases": [

    {

      "condition": "effective_date outside of pay_period",

      "impact": "Entry will not process in expected period. Must match effective date to pay period or entry will be skipped.",

      "severity": "high"

    }

  ]

}

```

This structure means the expertise lives in the JSON, not in the prompt. Adding a new scenario or a new edge case is a file edit, not a code change. The knowledge base hot-reloads, so updates go live without a restart.

The Architecture on Databricks

Running this on Databricks was a deliberate choice. The team already uses the platform, so authentication, security, and data governance come for free. Here is the technical stack:

- Databricks Apps for hosting the Flask application

- Databricks Foundation Model API to call Claude (Sonnet 4.5 at time of writing) without managing any external API credentials or you can use the OCI LLM API and connect to it using Python from within the solution

- Unity Catalog Delta tables for two purposes: structured logging of every interaction to `ef_dv.raw_dev_metadata.solution_designer_logs`, and session persistence in `ef_dv.raw_dev_metadata.conversation_sessions`

- Serverless SQL Warehouse for querying those Delta tables from the app

- On-behalf-of (OBO) authentication so every request to Databricks runs under the identity of the actual user, not a shared service account

The logging design deserves a mention. Every time a user generates a solution, submits feedback, or asks a follow-up question, a structured record lands in the Delta table with fields for user identity, scenario ID, scenario category, satisfaction rating, time saved, duration, and the interaction text. That gives leadership a real ROI dashboard backed by queryable data rather than estimates.

How We Built This With Agentic Development

The development process itself is worth describing because it reflects a pattern that works well for Oracle-specific tooling.

We used GitHub Copilot in agent mode throughout the build. The agent did not just autocomplete code; it was given feature requirements and asked to reason through the implementation, identify edge cases in its own output, and iterate. The key discipline was keeping the agent's scope narrow. Each session had one focused objective: add session persistence, add the feedback loop, fix a specific datetime bug in Delta table reads, resolve an issue with the resume-session banner showing stale state.

This approach works well for Oracle support tooling for a specific reason: Oracle Cloud problems are well-bounded. The diagnostic questions for a 3-way match hold resolution are not the same as the diagnostic questions for an HCM Fast Formula error. That domain specificity is an asset when working with an AI coding agent because you can describe the scenario structure precisely and the agent can reason about it correctly.

The iterative cycle looked like this:

1. Identify a gap in the user experience (example: returning to a previously solved scenario still presented the rating form instead of the completed state).

2. Trace the root cause through the code. In this case, the `/feedback` endpoint stored the rating on the session's last interaction in the Delta table but intentionally left session status as `active`. The frontend never checked whether the last interaction already had feedback attached.

3. Write a targeted fix. The solution was a new `restoreFeedbackStateFromHistory()` function in the frontend that reads the persisted rating, locks the feedback buttons, skips the rating form, and surfaces the "Generate Training Doc" button directly. No backend changes needed.

4. Run the 329-test suite to verify no regressions.

5. Deploy with the PowerShell script that syncs files to the Databricks workspace and triggers a new app deployment.

6. Confirm SUCCEEDED in the Databricks Apps deployment status.

The agent accelerated every step but did not replace the domain judgment calls. Decisions like "should the session status flip to solved when feedback is submitted, or should we leave it active so users can keep the conversation going?" require understanding the Oracle support workflow. The agent implements whatever direction you give it; you still have to give the right direction.

What This Looks Like in Practice

Consider a real scenario: an Oracle Finance team is getting 3-way match holds on vendor invoices. Previously, a ticket would come in, a knowledgeable team member would spend 15 to 45 minutes asking diagnostic questions via email or a Teams chat, and then write up a resolution.

With Solution Designer, the user navigates to the "3-Way Match Hold Resolution in Payables" scenario. They answer questions about hold type (quantity vs. price variance), tolerance settings, receipt status, PO type, and approval status. The tool detects relevant edge cases -- for example, if it is a price variance hold on a blanket PO, there is a specific Oracle behavior around line-level vs. header-level tolerances that trips people up repeatedly. The solution it generates addresses exactly that combination. If the user is satisfied, they rate the response, click "Generate Training Doc," specify their audience as "Oracle Finance users," and download a formatted guide they can drop into their SharePoint or Confluence space.

The time saved compounds across every person who hits that scenario going forward.





Click on the Images to Expand Them~

What We Learned

A few things stand out after building this:

Structure beats prompting. The quality improvement from giving AI structured inputs with pre-evaluated edge cases is larger than any prompt engineering trick. When the model knows that the effective date is outside the pay period because the scenario definition explicitly flagged it, the response is categorically more useful than when the user tries to describe that situation in free text.

Persistence changes the support dynamic. When solutions survive as resumable sessions in Delta, the tool stops being a one-shot query tool and starts being a case management layer. Users come back to the same session when a problem resurfaces, add follow-up context, and build a richer record of what was tried and what worked.

Feedback closes the loop. The satisfaction ratings and time-saved estimates that land in the Delta log are not vanity metrics. They identify which scenarios are working and which ones need better edge case coverage. The scenarios with low success rates are the ones that need a knowledge base update. That is a tractable engineering task.

Domain expertise encodes well into JSON. Oracle Cloud has well-documented configuration patterns and well-known failure modes. That knowledge, once captured in the scenario JSON format, is reusable forever. An experienced Oracle consultant or admin can encode years of diagnostic heuristics in an afternoon and make them available to everyone on the team immediately.

Getting Started If You Want to Build Something Similar

The approach is not specific to this stack. The core pattern is: structured intake + knowledge-encoded edge cases + LLM synthesis + persistent sessions. You need:

- A way to call a capable LLM (Databricks Foundation Model API, OCI LLM, Azure OpenAI, or similar)

- A JSON or database structure to encode your domain knowledge

- A lightweight web framework (Flask works well; FastAPI is another good option)

- A persistence layer for sessions and logs (Delta on Databricks is convenient if you are already there; a Postgres database works just as well and of course OCI Autonomous Databases!)

If your organization runs Oracle Cloud and has people who have been troubleshooting it for years, you already have the hardest ingredient: the domain knowledge. The tool just gives you a way to make it available at scale.

The knowledge base for this project started with five scenarios based on the most frequent support tickets. It now covers 31. Each new scenario takes roughly two to four hours to build out properly, including the edge cases. That is a reasonable investment for a scenario that generates 20 support tickets a month.

If you are building something similar for your Oracle user community, the questions, edge case structures, and session management patterns described here translate directly. The specific scenarios are where your team's expertise goes -- everything else is scaffolding.

Monday, June 8, 2026

How I Connected Oracle OCI LLM Endpoints to Postman and VS Code

I recently spent some time wiring up Oracle Cloud Infrastructure Generative AI endpoints so I could call models directly with an OCI Generative AI API key, validate everything in Postman, and then take the same setup into Visual Studio Code. The process ended up being a great example of how OCI can fit into modern AI workflows without forcing teams to abandon the tools they already use every day. Oracle’s Generative AI service supports service specific API keys, OpenAI compatible endpoints, and both Chat Completions and Responses APIs, which makes it much easier to integrate enterprise hosted models into familiar developer tooling.

What stood out to me most was how practical the setup became once the moving parts were understood. OCI Generative AI API keys are not the same as standard OCI IAM API keys. They are service generated secrets created specifically for OCI Generative AI, and Oracle documents that either of the two generated secrets can be used interchangeably in the Authorization header when calling supported model endpoints in the same region where the key was created.

Step 1: Creating the OCI Generative AI API Key

The first step was creating an API key inside the OCI Generative AI area of the Oracle Cloud console. Oracle documents these as service specific credentials for model access, and that distinction matters because they are meant for LLM endpoint authentication, not for general tenancy administration. Oracle also notes that the key must be used in the same OCI region as the model endpoint, which is important when you are testing against a region specific inference URL.

Another helpful detail is that OCI gives you two interchangeable secrets per API key. That makes rotation easier because one secret can be regenerated while the other remains active. Oracle explicitly recommends using one of those secrets as the bearer token when calling a supported model endpoint.

Step 2: Adding the IAM Policy That Makes the Key Work

Creating the API key was only part of the story. The key also needed permission to call the OCI Generative AI service. Oracle’s documentation explains that a separate IAM policy is required for principals of type generativeaiapikey, and this is where a lot of integration attempts can stall if the policy step is skipped.

In my case, I created the policy in the OCI Console under *Identity & Security > Policies* and used the manual editor in the root compartment. For testing, the policy that finally unlocked the flow was:

```text

allow any-user to use generative-ai-family in tenancy where ALL {request.principal.type='generativeaiapikey'}

```

Oracle documents this pattern for broad testing access and also explains that policies can be narrowed later by compartment, model, operation type, or even a specific API key OCID. That is a good way to start wide enough to validate the integration and then tighten the scope after the path is proven.

Step 3: Calling the OCI Endpoint from Postman

Once the key and policy were in place, I moved into Postman. Oracle documents a REST endpoint pattern for Chat Completions using OCI Generative AI API keys:

```text

https://inference.generativeai.<region>.oci.oraclecloud.com/20231130/actions/v1/chat/completions

```

Oracle’s API key documentation also shows that the request should send the API key secret in the Authorization: Bearer ... header and include a valid supported model in the request body. Supported models for this API key based REST path include xAI Grok and OpenAI GPT OSS, which are the models I focused on, but there's more available models in OCI like Llama, Cohere and Gemini.

My working request in Postman ended up looking like this:

```http

POST https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/20231130/actions/v1/chat/completions

Authorization: Bearer sk-<your-secret>

Content-Type: application/json

Accept: application/json

```

With a body like this:

```json

{

  "model": "openai.gpt-oss-20b",

  "messages": [

    {

      "role": "user",

      "content": "Say hello in one sentence."

    }

  ]

}

```

After the policy was added, that request returned a successful response. That was the turning point because it confirmed the key, the policy, the endpoint, and the region were all aligned correctly. Oracle’s documentation supports this exact pattern, including the Chat Completions endpoint and the use of a bearer token generated by OCI Generative AI.


Click the image to expand it~

What I Learned From the Postman Troubleshooting

The troubleshooting was actually a useful part of the exercise. Early failures came down to a few very specific issues. First, the bearer token has to be the actual `sk-...` secret, not the API key OCID or a console URL. Second, the key has to be used in the same region where it was created. Third, the IAM policy really is required or the request will not succeed even if the secret is correct. Oracle’s docs are clear on all three of those points, and once those pieces clicked, the flow became much more predictable.

That experience also reinforced something broader. OCI is not just exposing models in its own console. Oracle is making the service available in ways that work with the tools many engineering teams already use, which lowers the friction to experiment and integrate. Oracle’s newer OpenAI compatible endpoint documentation makes that intent even more obvious by describing a base endpoint that works with familiar OpenAI style request patterns while still keeping authentication, execution, and resource management inside OCI.

Step 4: Taking the Same OCI Endpoint into VS Code

After confirming the endpoint in Postman, I wanted the same model access inside Visual Studio Code, given it's broad use in our organization. That turned out to be possible using VS Code’s bring your own key model support. Microsoft’s documentation explains that VS Code lets you add language models through the model picker and that custom providers can expose one provider with many models. The model metadata includes fields such as id, name, maxInputTokens, maxOutputTokens, and capability flags like tool calling and image input.

Using the custom endpoint option in the VS Code model picker opened a configuration file where I defined the OCI model settings. I used a Chat Completions style configuration because I had already validated that path in Postman. The key pieces were the OCI endpoint URL, the OCI API key, and the exact model ID. For example, openai.gpt-oss-20b worked well for a first pass because it had already succeeded in Postman, and Oracle lists GPT OSS as a supported model family for API key based Chat Completions.

The result was that I could select the OCI backed model in VS Code’s chat experience and use it like any other language model available through the model picker. Microsoft documents that the model picker is how users switch chat models, and Oracle documents that OCI supports both native and OpenAI compatible inference patterns. That combination is what made this work so well.

Click the image to expand it~

Why This Matters

To me, the bigger takeaway is not just that I got Postman and VS Code working. It is that OCI can participate in the same AI development workflows people already use for testing, coding, prototyping, and experimentation. Oracle’s documentation highlights support for OpenAI compatible endpoints, supported SDKs, and familiar APIs like Chat Completions and Responses. Microsoft’s documentation shows that VS Code is increasingly flexible about model choice through bring your own key and custom providers. Put those together and you have a path for teams that want enterprise hosted AI models without giving up developer ergonomics.

That opens up a lot of possibilities. It means OCI hosted models can be validated in Postman, consumed by scripts and SDKs, and surfaced directly in the editor where developers work. It also means organizations that are already invested in Oracle can extend that platform into modern AI workflows instead of treating it as something separate. OCI Generative AI is positioned by Oracle as an enterprise scale AI platform that supports hosted models, OpenAI compatible APIs, governance, and agent related features. This kind of integration work shows what that can look like in practice.

Final Thoughts

What started as a simple attempt to call a model with an OCI API key turned into a good exercise in understanding how Oracle has structured access, authorization, and compatibility with recent product enhancements. The final setup was straightforward once the pieces were in place: create the API key, grant the IAM policy, validate the endpoint in Postman, and then carry the same working endpoint into VS Code. Oracle’s API key model, policy framework, and OpenAI compatible options make that path realistic, and it is a strong example of OCI being useful well beyond the console itself.

If you are working in OCI and want to make enterprise hosted LLMs available in tools your team already trusts, this is absolutely worth trying.

Saturday, March 14, 2026

Converting Oracle’s 1,155 Page EPM REST API PDF Into Machine Readable JSON and Markdown and What It Unlocks

While working through several integration and automation use cases involving Oracle Enterprise Performance Management Cloud, our team kept running into the same practical challenge. The APIs themselves were capable, well designed, and supported a wide range of enterprise scenarios. The challenge was not the APIs. It was how quickly and precisely we could work with the documentation.

The official EPM REST API reference is a 1,155 page PDF.

That document is thorough and authoritative. It reflects significant investment from Oracle and provides deep coverage of the platform. As our use cases expanded to include automation, AI assisted development, and reusable integration patterns, we started asking a different question. What happens when that same high quality documentation is available in a form that tools can understand just as easily as people?

That question led us down an interesting path.

Why structure matters

When teams build against the EPM Planning REST API, the needs are usually very specific. Engineers need to know exactly which endpoint to call, which parameters are required, how asynchronous jobs behave, and how to interpret the response.

The information already exists in the documentation. The challenge is not accuracy or completeness. The challenge is that the information is optimized for reading, not for reuse by modern tooling or AI.

As development workflows increasingly involve AI coding assistants and automated pipelines, having clean structured context becomes essential. These tools perform best when they can reason over well defined inputs rather than scanning long blocks of unstructured text.

The goal here was not to critique how the documentation is published today. It was to explore how much additional value could be unlocked by reshaping it into formats that better align with how software is now being built.

What was built

As part of this effort, a Python script was created to extract and restructure the Oracle EPM REST API documentation. The script processes the official EPM REST API PDF, document G42939 02 from November 2025 on docs.oracle.com, extracts the full text using pdfplumber, and transforms it into structured outputs.

The first output is a structured JSON file. It captures authentication methods including Basic Authentication and OAuth 2.0 with precise header formats. It includes identity domain rules for test and production environments. It documents thirty four REST API endpoints across six functional areas with method, path, parameters, request details, response details, and required roles. It also includes twenty five supported job types with descriptions, along with status codes and other reference data that comes up frequently during development.

The second output is a Markdown version of the same information. This format is easier for humans to scan and review, while still preserving structure through headings, tables, and code blocks.

In addition, the full extracted text from the PDF is saved as a plain text file. This provides traceability back to the source material when deeper validation or cross checking is needed.

How the information is organized

The structured output is grouped by API domain.

Planning includes nineteen endpoints covering jobs, data slices, members, variables, substitution variables, applications, and Smart Push.

Migration includes seven endpoints covering snapshots, file operations, and service maintenance.

Security includes two endpoints focused on encryption key management.

User Management includes three endpoints for users, groups, and role assignments.

Reporting includes one endpoint for report extraction.

Data Management includes two endpoints for integration job execution.

Each endpoint follows a consistent and predictable structure. That consistency is what allows the documentation to move from something that must be read manually to something that can be consumed directly by tools.

Once the documentation exists in this form, it becomes much easier to integrate into development workflows rather than sitting on the side as a reference that is consulted only when something goes wrong.

What this enables

The most immediate benefit shows up when working with AI assisted development tools.

With a structured JSON reference available, coding assistants can reason about the EPM API surface area accurately. They can identify valid endpoints, understand required parameters, recognize supported job types, and generate correct request patterns without guesswork.

This changes the nature of development work. Teams spend less time validating endpoint paths and correcting assumptions, and more time focusing on orchestration, error handling, and business logic.

It also enables more advanced patterns. For teams experimenting with agents that interact with enterprise systems by running jobs, polling for completion, and exporting results, a machine readable API contract is a prerequisite. This approach provides that contract without changing the underlying APIs.

Nothing about the EPM APIs themselves changes. What changes is how easily they can be incorporated into modern tooling and automated workflows.

Notes on the extraction approach

The extraction process is straightforward in concept but careful in execution. pdfplumber handles the low level PDF text extraction. The more challenging part is identifying structure such as endpoint headers, HTTP methods, parameter sections, and response schemas.

Oracle’s documentation is internally consistent, which made this feasible. The script relies on that consistency along with targeted pattern matching and heuristics designed specifically around the EPM REST API layout.

This is not intended to be a generic solution for converting any PDF into structured data. It is a practical pipeline built to produce reliable and usable output for a specific enterprise API.

One interesting outcome is the level of compression involved. The source document is 1,155 pages long. The structured JSON representation is under one thousand lines. That difference highlights how much of a traditional API PDF consists of layout, repetition, and presentation rather than core technical meaning.

Looking ahead

As software development continues to evolve toward closer collaboration between humans and machines, documentation becomes even more important. The format simply needs to keep pace with how it is used.

JSON and MD represent an ideal state for AI interoperability. For platforms that still rely primarily on PDF or other types of documentation, there is an opportunity to expand how that information can be consumed and reused without replacing what already exists.

For teams working with complex enterprise APIs, the takeaway is straightforward. If the documentation exists, it can be made more useful. Extracting it, structuring it, and integrating it into development workflows can unlock real gains in speed, accuracy, and confidence.

That is what this effort set out to explore, and the results have already shown clear value in practice.

Get the code

The extraction script, along with the structured JSON output and the Markdown reference, is available in the GitHub repository here:

https://github.com/TheOwner-glitch/oracle_epm_rest_api/tree/main

The repository includes the Python script used to extract and structure the documentation, the machine readable JSON reference, and a Markdown version that is easier to browse and review. Together, these files provide a practical starting point for teams working with Oracle EPM REST APIs who want documentation that can be consumed directly by modern development tools.

The broader repository also includes supporting artifacts related to interacting with Oracle EPM Cloud, but the API reference extraction stands on its own as a useful and reusable asset.

If this approach proves useful or is adapted for other platforms or documentation sets, those lessons are worth sharing.