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.

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.
Need more testing? Create a free account to get 200 free credits (equals 200 Receipt scans).

Implementation: C# .NET Integration

The Receipt API has been upgraded while the `/v1/receipt` endpoint remains unchanged. It returns the current flat response schema by default. Standard mode costs 1 credit; append `?accuracy=enhanced` for enhanced processing at 2 credits (JPG, PNG, or WebP). 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, totals, validation status, and individual line items.

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

CSHARP EXAMPLE
// 💰 Get 200 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.MerchantName}");
                Console.WriteLine($"Date:      {data.Date}");
                                Console.WriteLine($"Tax:       {data.TaxAmount}");
                                Console.WriteLine($"Total:     {data.TotalAmount} {data.Currency}");
                Console.WriteLine($"Status:    {data.Status}");

                Console.WriteLine("\n--- Purchased Items ---");
                if (data.Items != null)
                {
                    foreach (var item in data.Items)
                    {
                        Console.WriteLine($"- {item.Name}: {item.Quantity}x = {item.Price}");
                    }
                }
            }
            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
{
    [JsonPropertyName("response_version")]
    public int ResponseVersion { get; set; }
    [JsonPropertyName("merchant_name")]
    public string MerchantName { get; set; }
    public string Date { get; set; }
    public string Time { get; set; }
    public string Currency { get; set; }
    [JsonPropertyName("total_amount")]
    public decimal? TotalAmount { get; set; }
    [JsonPropertyName("tax_amount")]
    public decimal? TaxAmount { get; set; }
    public List<LineItem> Items { get; set; }
    public string Status { get; set; }
}

public class LineItem
{
    public string Name { get; set; }
    public decimal? Quantity { get; set; }
    public string Price { get; set; }
}

Technical Specs

  • •Latency: < 3s (Optimized for mobile connections)
  • •Availability: Served from Cloudflare's global edge network
  • •Data Privacy: Images kept for at most 24 hours for quality spot-checks, then deleted (GDPR, SOC 2 Type II)
  • •Input: JPG, PNG, WebP (Base64 Encoded)
  • •Max File Size: 4.5MB
  • •Output: Current flat Receipt JSON object

Key Features

  • •Mobile-First Preprocessing: Automatically corrects perspective, rotation, and shadows common in smartphone photography.
  • •Tax & Total Detection: Extracts tax and final total amounts while preserving unknown values as null.
  • •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": {
    "response_version": 2,
    "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,
    "status": "complete",
    "issues": []
  }
}

Frequently Asked Questions

How are handwritten tips handled on restaurant receipts?

Handwritten additions may be reflected in the extracted final total when legible, but the API does not return a separate tip field. Review low-confidence or partial results before automating reimbursement.

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 keeps uploaded images and results for at most 24 hours for quality spot-checks, then deletes them.

You May Also Like

Related tutorials, platform guides, and comparisons

Tutorial

PHP Receipt OCR API

Tutorial: Integrate the StructOCR Receipt API into your PHP web applications. Upload an image for a free test! Extract merchants, totals, and line items from POS receipts using raw cURL or Guzzle.

PHP · Receipt
Tutorial

Java Receipt OCR API

Tutorial: Integrate StructOCR's Receipt API into your Java enterprise applications. Upload an image for a free test! Extract line items, merchants, and taxes from POS receipts into structured JSON.

Java · Receipt
Tutorial

Go Receipt OCR API

Upload an image for a free test! Tutorial: Build scalable expense reporting apps in Go. Learn how to extract merchants, line items, and totals from POS receipts using our Golang OCR integration.

Go · Receipt
Tutorial

Python Receipt OCR API SDK

Tutorial: Extract merchants, line items, and totals from receipts using the StructOCR Python SDK. Upload an image for a free test! Ideal for fintech ETL pipelines, AI accounting, and Pandas dataframes.

Python · Receipt
Tutorial

Node.js Receipt OCR API SDK

Tutorial: Integrate the StructOCR Node.js SDK to extract structured data from retail receipts. Upload an image for a free test! Parse merchants, totals, and line items in your Javascript backends.

Node.js · Receipt
Tutorial

C# Shipping Container OCR API

Upload an image for a free test! Tutorial: Learn how to use the StructOCR C# Client to extract data from Shipping Containers. Extract ISO 6346 container numbers and check them against the ISO check digit. Includes code samples and JSON schemas.

C# · Container
Tutorial

C# License Plate OCR API

C# License Plate OCR tutorial. Upload an image for a free test! Accurately extract global license plates, native scripts, colors, and vehicle types.

C# · License Plate
Tutorial

C# Vehicle Registration OCR API

C# Vehicle Registration OCR API tutorial. Upload an image for a free test! Accurately extract standardized fields like VIN, make, and model, along with dynamically localized data for global documents.

C# · Vehicle Reg.
Tutorial

C# Passport OCR API

Upload an image for a free test! High-accuracy C# Passport OCR API for parsing MRZ data. Get structured JSON output from passport images. Eliminate Tesseract errors and manual entry.

C# · Passport
Tutorial

C# Weighbridge Ticket OCR API Tutorial

Integrate weighbridge ticket OCR in C# and .NET. Send a Base64 image and extract vehicle, material, gross, tare, net, and validation fields as JSON.

C# · Weighbridge Ticket

Technical Comparisons & Integrations

Explore platform integrations and competitive analysis

From tutorial to production in 5 minutes.

You've seen the code. Now get your API key, grab your 200 free credits, and see it work with your own images. No credit card required.

Instant Access Cancel Anytime No Credit Card