The C# Receipt OCR API for Expense Tracking

Instantly convert photos of thermal paper and POS receipts into structured JSON data. Built for mobile uploads and accounting automation.

Diagram demonstrating a mobile photo of a crumpled restaurant receipt being processed by the StructOCR API and outputting a JSON object with merchant, tip, tax, and total fields.
Figure 1: StructOCR instantly parses smartphone photos of receipts into standardized expense data.

The Challenge of Parsing Mobile Receipts

Unlike standard digital documents, retail and dining receipts present unique computer vision challenges. Users typically photograph them using smartphones under poor lighting conditions, resulting in shadows, glare, and skewed angles. Furthermore, thermal paper often fades, and receipts are frequently folded or crumpled. When developers try to use generic text-extraction libraries, they get back an unstructured wall of coordinates. Writing custom logic to differentiate between a subtotal, a tax amount, and a handwritten tip across thousands of different store layouts is an endless maintenance nightmare.

Intelligent Expense Extraction with StructOCR

StructOCR solves this by bypassing template-based rules entirely. Our engine uses layout-aware machine learning models trained specifically on millions of global POS receipts. It automatically handles image deskewing and contrast enhancement before identifying key semantic fields. By integrating our Receipt OCR API, your C# application receives clean, standardized JSON containing the merchant's name, transaction date, line items, and financial breakdown (including taxes and gratuity). This allows developers to build seamless expense management automation tools without touching computer vision code.

Common Integration Scenarios

  • Expense Reporting Apps: Enable 'snap and go' features in your SaaS. Employees take a photo, and the app auto-populates the reimbursement claim instantly.
  • Loyalty & Cashback Programs: Scan user-uploaded shopping receipts to verify proof of purchase for specific brand SKUs and automatically award loyalty points.
  • Automated Bookkeeping: Map raw receipt data directly into accounting software like QuickBooks or Xero, matching transactions to bank feeds seamlessly.

Implementation: C# .NET Integration

This C# example uses `HttpClient` to submit a receipt image to the API. It demonstrates how to strongly type the JSON response to easily access the merchant name, tip amount, and individual line items.

Prerequisite: .NET Core 3.1+ or .NET 5/6/7/8+

CODE EXAMPLE
// šŸ’° Get 20 free credits instantly to test your own receipts:
// šŸ‘‰ https://structocr.com/register

using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using System.Collections.Generic;

public class ReceiptOcrExample
{
    private const string ApiKey = "YOUR_API_KEY_HERE";
    // Note the endpoint is specific to receipts
    private const string ApiEndpoint = "https://api.structocr.com/v1/receipt";

    private static readonly HttpClient client = new HttpClient();

    public static async Task Main(string[] args)
    {
        string imagePath = "coffee_receipt.jpg";

        if (!File.Exists(imagePath))
        {
            Console.WriteLine($"Error: File not found at {imagePath}");
            return;
        }

        try
        {
            // 1. Base64 Encode the Image
            byte[] imageBytes = await File.ReadAllBytesAsync(imagePath);
            string base64Image = Convert.ToBase64String(imageBytes);
            var payload = new { img = base64Image };

            // 2. Configure Headers
            client.DefaultRequestHeaders.Clear();
            client.DefaultRequestHeaders.Add("x-api-key", ApiKey);

            // 3. Execute POST Request
            Console.WriteLine($"Analyzing receipt via {ApiEndpoint}...");
            HttpResponseMessage response = await client.PostAsJsonAsync(ApiEndpoint, payload);
            string responseBody = await response.Content.ReadAsStringAsync();

            if (!response.IsSuccessStatusCode)
            {
                Console.WriteLine($"API Error ({response.StatusCode}): {responseBody}");
                return;
            }

            // 4. Parse the Structured Data
            var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
            var result = JsonSerializer.Deserialize<ApiResponse>(responseBody, options);

            if (result?.Success == true && result.Data != null)
            {
                var data = result.Data;
                Console.WriteLine("\nāœ… Receipt Parsed Successfully!");
                Console.WriteLine($"Merchant:  {data.Merchant?.Name}");
                Console.WriteLine($"Date:      {data.Date}");
                Console.WriteLine($"Subtotal:  {data.Financials?.Subtotal}");
                Console.WriteLine($"Tax:       {data.Financials?.TaxAmount}");
                Console.WriteLine($"Tip:       {data.Financials?.TipAmount}");
                Console.WriteLine($"Total:     {data.Financials?.TotalAmount} {data.Currency}");

                Console.WriteLine("\n--- Purchased Items ---");
                if (data.LineItems != null)
                {
                    foreach (var item in data.LineItems)
                    {
                        Console.WriteLine($"- {item.Description}: {item.Quantity}x @ {item.UnitPrice} = {item.Amount}");
                    }
                }
            }
            else
            {
                Console.WriteLine($"Extraction Failed: {result?.Error}");
            }
        }
        catch (Exception e)
        {
            Console.WriteLine($"Unexpected Error: {e.Message}");
        }
    }
}

// --- Data Models ---
public class ApiResponse
{
    public bool Success { get; set; }
    public ReceiptData Data { get; set; }
    public string Error { get; set; }
}

public class ReceiptData
{
    public string Date { get; set; }
    public string Time { get; set; }
    public string Currency { get; set; }
    public MerchantData Merchant { get; set; }
    public FinancialData Financials { get; set; }
    
    [JsonPropertyName("line_items")]
    public List<LineItem> LineItems { get; set; }
}

public class MerchantData
{
    public string Name { get; set; }
    public string Address { get; set; }
    public string Phone { get; set; }
}

public class FinancialData
{
    public decimal? Subtotal { get; set; }
    [JsonPropertyName("tax_amount")]
    public decimal? TaxAmount { get; set; }
    [JsonPropertyName("tip_amount")]
    public decimal? TipAmount { get; set; }
    [JsonPropertyName("total_amount")]
    public decimal? TotalAmount { get; set; }
}

public class LineItem
{
    public string Description { get; set; }
    public decimal? Quantity { get; set; }
    [JsonPropertyName("unit_price")]
    public decimal? UnitPrice { get; set; }
    public decimal? Amount { get; set; }
}

Technical Specs

  • •Latency: < 3s (Optimized for mobile connections)
  • •Uptime: 99.9% SLA
  • •Data Privacy: Zero data retention (GDPR & SOC2 Compliant)
  • •Input: JPG, PNG, WebP (Base64 Encoded)
  • •Max File Size: 4.5MB
  • •Output: JSON (Nested Structure)

Key Features

  • •Mobile-First Preprocessing: Automatically corrects perspective, rotation, and shadows common in smartphone photography.
  • •Tax & Gratuity Detection: Distinguishes between base amounts, local taxes (VAT/GST), and handwritten tips on restaurant bills.
  • •Faded Ink Recovery: Advanced contrast algorithms recover data from older, degraded thermal paper prints.

Sample JSON Response

By receiving a highly predictable structure, you can bind the JSON payload directly to your Go interfaces without messy intermediary parsing.

{
  "success": true,
  "data": {
    "is_valid": true,
    "confidence": "high",
    "merchant_name": "Blue Bottle Coffee",
    "date": "2026-04-22",
    "time": "08:45 AM",
    "currency": "USD",
    "total_amount": 14.5,
    "tax_amount": 1.25,
    "items": [
      {
        "name": "Caffe Latte - Large",
        "quantity": 2,
        "price": "11.00"
      },
      {
        "name": "Butter Croissant",
        "quantity": 1,
        "price": "3.50"
      }
    ],
    "validation_error": null
  }
}

Frequently Asked Questions

Can the API read handwritten tips on restaurant receipts?

Yes. Our models are trained to recognize both printed text and handwritten additions commonly found on the merchant copy of dining receipts, accurately extracting the written tip and calculating the final total.

How do I handle multi-page receipts (like long grocery bills)?

For exceptionally long continuous thermal receipts, you can capture multiple overlapping photos and submit them. The API will process the items; however, for best results, we recommend keeping the entire receipt within a single legible frame if possible.

Is user financial data safe?

Absolutely. StructOCR operates on a strict zero-retention policy. Receipt images are processed in memory to extract the JSON data and are instantly destroyed. We do not store, view, or train on your customers' financial data.

More OCR Tutorials

Precise Data Extraction and Seamless Integration with AI-powered OCR API.

Empower your solutions with automated data extraction by integrating best-in class StructOCR via API seamlessly.

No credit card required • Full API access included