How to Integrate Azure OpenAI for payments with CosmosDB for startups

By Cyprian AaronsUpdated 2026-04-21
azure-openai-for-paymentscosmosdbstartups

Azure OpenAI gives you the reasoning layer for payment workflows: classify intents, extract fields from invoices, flag suspicious transactions, and generate customer-facing responses. CosmosDB gives you the durable state layer: store payment sessions, retries, audit trails, and conversation memory without fighting schema migrations.

For startups building AI agents around payments, this combo is practical. You get an agent that can read a payment request, decide what to do next, and persist every decision for compliance and recovery.

Prerequisites

  • Python 3.10+
  • An Azure subscription
  • An Azure OpenAI resource with:
    • endpoint
    • api_key
    • a deployed model name like gpt-4o-mini
  • An Azure Cosmos DB account with:
    • endpoint
    • key
    • database and container created
  • pip installed
  • Environment variables set:
    • AZURE_OPENAI_ENDPOINT
    • AZURE_OPENAI_API_KEY
    • AZURE_OPENAI_DEPLOYMENT_NAME
    • COSMOS_ENDPOINT
    • COSMOS_KEY
    • COSMOS_DATABASE_NAME
    • COSMOS_CONTAINER_NAME

Install the SDKs:

pip install openai azure-cosmos python-dotenv

Integration Steps

1) Initialize Azure OpenAI and CosmosDB clients

Use the Azure OpenAI chat client for payment reasoning, and CosmosDB for persistence. Keep them in separate modules in real projects; here they live together so you can see the flow end to end.

import os
from dotenv import load_dotenv
from openai import AzureOpenAI
from azure.cosmos import CosmosClient, PartitionKey

load_dotenv()

aoai_client = AzureOpenAI(
    api_key=os.environ["AZURE_OPENAI_API_KEY"],
    api_version="2024-06-01",
    azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
)

cosmos_client = CosmosClient(
    url=os.environ["COSMOS_ENDPOINT"],
    credential=os.environ["COSMOS_KEY"],
)

database_name = os.environ["COSMOS_DATABASE_NAME"]
container_name = os.environ["COSMOS_CONTAINER_NAME"]

database = cosmos_client.create_database_if_not_exists(id=database_name)
container = database.create_container_if_not_exists(
    id=container_name,
    partition_key=PartitionKey(path="/payment_id"),
)

2) Define the payment extraction prompt

The agent should turn raw payment text into structured JSON. That makes it easy to validate fields before writing anything to CosmosDB.

import json

def extract_payment_details(raw_text: str) -> dict:
    response = aoai_client.chat.completions.create(
        model=os.environ["AZURE_OPENAI_DEPLOYMENT_NAME"],
        messages=[
            {
                "role": "system",
                "content": (
                    "You extract structured payment data from user messages. "
                    "Return only valid JSON with keys: "
                    "payment_id, payer_name, amount, currency, due_date, "
                    "merchant, confidence."
                ),
            },
            {"role": "user", "content": raw_text},
        ],
        temperature=0,
    )

    content = response.choices[0].message.content
    return json.loads(content)

3) Store the extracted payment record in CosmosDB

Use CosmosDB as your source of truth for payment workflow state. A simple pattern is to write an initial record with status pending_review, then update it after downstream checks.

from datetime import datetime, timezone

def save_payment_record(payment: dict) -> dict:
    item = {
        "id": payment["payment_id"],
        "payment_id": payment["payment_id"],
        "payer_name": payment["payer_name"],
        "amount": payment["amount"],
        "currency": payment["currency"],
        "due_date": payment["due_date"],
        "merchant": payment["merchant"],
        "confidence": payment["confidence"],
        "status": "pending_review",
        "created_at": datetime.now(timezone.utc).isoformat(),
    }

    container.upsert_item(item)
    return item

4) Add an approval or risk check using Azure OpenAI

This is where the agent becomes useful for payments. Ask the model to review the structured data and decide whether it looks safe enough to proceed or whether it needs manual review.

def assess_payment_risk(payment: dict) -> dict:
    response = aoai_client.chat.completions.create(
        model=os.environ["AZURE_OPENAI_DEPLOYMENT_NAME"],
        messages=[
            {
                "role": "system",
                "content": (
                    "You are a payments risk assistant. "
                    "Return only valid JSON with keys: decision, reason."
                ),
            },
            {
                "role": "user",
                "content": f"Assess this payment for risk:\n{json.dumps(payment)}",
            },
        ],
        temperature=0,
    )

    return json.loads(response.choices[0].message.content)

5) Update CosmosDB with the final workflow state

Once the agent decides what to do next, persist that decision. This gives you auditability and lets other services pick up the record later.

def process_payment_request(raw_text: str):
    payment = extract_payment_details(raw_text)
    saved = save_payment_record(payment)
    risk = assess_payment_risk(saved)

    saved["status"] = risk["decision"]
    saved["risk_reason"] = risk["reason"]
    saved["updated_at"] = datetime.now(timezone.utc).isoformat()

    container.upsert_item(saved)
    return saved

result = process_payment_request(
    "Invoice INV-2048 from Acme Supplies for $420 USD due on 2026-05-01"
)
print(result)

Testing the Integration

Run a simple end-to-end test with a known input. You want to verify three things:

  • Azure OpenAI returns valid JSON
  • CosmosDB accepts the record
  • The stored status updates after risk assessment
test_input = "Payment request PMT-1007 for Jane Doe paying $125 USD to CloudBooks due on 2026-04-30"
result = process_payment_request(test_input)

print("Stored record:")
print(json.dumps(result, indent=2))

stored_item = container.read_item(item=result["payment_id"], partition_key=result["payment_id"])
print("\nFetched from CosmosDB:")
print(json.dumps(stored_item, indent=2))

Expected output:

Stored record:
{
  "id": "PMT-1007",
  "payment_id": "PMT-1007",
  "payer_name": "Jane Doe",
  "amount": 125,
  "currency": "USD",
  "due_date": "...",
  "merchant": "CloudBooks",
  ...
}

Fetched from CosmosDB:
{
  ...
  "status": "...",
  ...
}

If your model returns malformed JSON, fix that first by tightening the system prompt or adding a JSON schema validation layer before writing to CosmosDB.

Real-World Use Cases

  • Invoice intake agent

    • Parse incoming invoice emails or PDFs into structured records.
    • Store every invoice in CosmosDB.
    • Use Azure OpenAI to flag missing fields or duplicate invoices.
  • Payment support copilot

    • Answer customer questions about failed payments or refund status.
    • Pull conversation history and transaction state from CosmosDB.
    • Generate consistent support responses through Azure OpenAI.
  • Fraud triage assistant

    • Score incoming payments based on patterns and metadata.
    • Persist alerts and analyst notes in CosmosDB.
    • Use Azure OpenAI to explain why a transaction was flagged in plain language.

The production pattern is simple: let Azure OpenAI interpret messy payment input, then use CosmosDB as the durable ledger for decisions and state. That split keeps your agent stateless at the reasoning layer and reliable at the storage layer.


Keep learning

By Cyprian Aarons, AI Consultant at Topiax.

Want the complete 8-step roadmap?

Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.

Get the Starter Kit

Related Guides