C#

Exemplos em C#

Seis exemplos prontos para copiar, da primeira chamada ao tratamento de erros, com a certidão de exemplo hospedada (dados fictícios).

Antes de começar

Três passos, uma vez só.

  1. Crie uma chave de API

    No painel, em Chaves de API.

  2. Guarde a chave no ambiente

    Na variável DOCSOCR_API_KEY, que os exemplos leem. O exemplo de preços não precisa de chave.

  3. Salve e rode

    Salve cada exemplo com o nome que aparece sobre o código. As primeiras linhas dizem do que ele precisa para rodar.

Primeira chamada

Envia a certidão de exemplo hospedada (dados fictícios) e mostra o JSON da resposta.

FirstCall.cs
// Your first call: extract the hosted sample certificate (fictitious data).
// Needs .NET 8+ and DOCSOCR_API_KEY in the environment. Run: dotnet run FirstCall.cs (.NET 10)
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;

using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(120) }; // above the API's 90 s extraction budget
http.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("DOCSOCR_API_KEY"));

var body = new JsonObject
{
    ["imageType"] = "url",
    ["imageUrl"] = "https://docsocr.com/samples/certidao-nascimento-exemplo.jpg",
    ["requestId"] = Guid.NewGuid().ToString(), // one id per document
};
using var content = new StringContent(body.ToJsonString(), Encoding.UTF8, "application/json");
using var response = await http.PostAsync("https://api.docsocr.com/api/v1/documents/birth-certificate", content);
using var answer = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
var root = answer.RootElement;

if ((int)response.StatusCode != 201 || !root.GetProperty("success").GetBoolean())
{
    Console.Error.WriteLine($"{(int)response.StatusCode} {root}");
    return 1;
}
Console.WriteLine(root.GetProperty("data").GetProperty("dados_pessoais").GetProperty("nome_completo").GetString());
return 0;

Arquivo local em base64

Lê uma imagem do seu computador e a envia em base64, sem precisar de uma URL pública.

LocalFile.cs
// Extract a certificate from a local file, sent in base64.
// Needs .NET 8+ and DOCSOCR_API_KEY in the environment. Run: dotnet run LocalFile.cs (.NET 10)
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;

var imageBase64 = Convert.ToBase64String(await File.ReadAllBytesAsync("certificate.jpg"));

using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(120) }; // above the API's 90 s extraction budget
http.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("DOCSOCR_API_KEY"));

var body = new JsonObject
{
    ["imageType"] = "base64",
    ["imageBase64"] = imageBase64,
    ["requestId"] = Guid.NewGuid().ToString(), // one id per document
};
using var content = new StringContent(body.ToJsonString(), Encoding.UTF8, "application/json");
using var response = await http.PostAsync("https://api.docsocr.com/api/v1/documents/birth-certificate", content);
using var answer = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
var root = answer.RootElement;

if ((int)response.StatusCode != 201 || !root.GetProperty("success").GetBoolean())
{
    Console.Error.WriteLine($"{(int)response.StatusCode} {root}");
    return 1;
}
Console.WriteLine(root.GetProperty("data").GetProperty("dados_pessoais").GetProperty("nome_completo").GetString());
return 0;

Imagem fora do padrão

Com resizeImage: true, uma imagem fora do nosso padrão de tamanho é redimensionada do nosso lado por 1 crédito a mais, em vez de recusada.

Resize.cs
// Extract an image outside our standard: resizeImage brings it to the
// standard first, for one extra credit (the 800x640 sample is too small).
// Needs .NET 8+ and DOCSOCR_API_KEY in the environment. Run: dotnet run Resize.cs (.NET 10)
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;

using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(120) }; // above the API's 90 s extraction budget
http.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("DOCSOCR_API_KEY"));

var body = new JsonObject
{
    ["imageType"] = "url",
    ["imageUrl"] = "https://docsocr.com/samples/certidao-nascimento-exemplo-800x640.jpg",
    ["requestId"] = Guid.NewGuid().ToString(), // one id per document
    ["resizeImage"] = true,
};
using var content = new StringContent(body.ToJsonString(), Encoding.UTF8, "application/json");
using var response = await http.PostAsync("https://api.docsocr.com/api/v1/documents/birth-certificate", content);
using var answer = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
var root = answer.RootElement;

if ((int)response.StatusCode != 201 || !root.GetProperty("success").GetBoolean())
{
    Console.Error.WriteLine($"{(int)response.StatusCode} {root}");
    return 1;
}
Console.WriteLine(root.GetProperty("data").GetProperty("dados_pessoais").GetProperty("nome_completo").GetString());
var resized = root.TryGetProperty("imageResized", out var flag) && flag.GetBoolean();
Console.WriteLine($"resized: {resized} credits: {root.GetProperty("creditsCharged")}");
return 0;

Motor fast

Pede o motor fast: ele é tentado primeiro, pelo preço dele, e os motores padrão respondem quando ele não consegue. A resposta diz qual motor respondeu e quanto custou.

Fast.cs
// Ask for the fast engine: it is tried first, at its own price, and the
// standard engines follow when it cannot answer. The answer names the engine
// that answered and what it cost.
// Needs .NET 8+ and DOCSOCR_API_KEY in the environment. Run: dotnet run Fast.cs (.NET 10)
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;

using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(120) }; // above the API's 90 s extraction budget
http.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("DOCSOCR_API_KEY"));

var body = new JsonObject
{
    ["imageType"] = "url",
    ["imageUrl"] = "https://docsocr.com/samples/certidao-nascimento-exemplo.jpg",
    ["requestId"] = Guid.NewGuid().ToString(), // one id per document
    ["engine"] = "fast",
};
using var content = new StringContent(body.ToJsonString(), Encoding.UTF8, "application/json");
using var response = await http.PostAsync("https://api.docsocr.com/api/v1/documents/birth-certificate", content);
using var answer = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
var root = answer.RootElement;

if ((int)response.StatusCode != 201 || !root.GetProperty("success").GetBoolean())
{
    Console.Error.WriteLine($"{(int)response.StatusCode} {root}");
    return 1;
}
Console.WriteLine($"engine: {root.GetProperty("engine").GetString()} credits: {root.GetProperty("creditsCharged")}");
return 0;

Erros e novas tentativas

Trata cada resposta e repete com o mesmo requestId: por 15 minutos, a repetição de uma requisição concluída recebe a mesma resposta, sem nova cobrança, e a de uma ainda em andamento recebe 409, para esperar.

Errors.cs
// Extract a certificate, handling every answer, with retries that never charge twice.
// Each retry sends the same requestId: a repeat of a finished request gets its
// kept answer at no charge, and a repeat of one still running is told to wait (409).
// Needs .NET 8+ and DOCSOCR_API_KEY in the environment. Run: dotnet run Errors.cs (.NET 10)
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;

const string Endpoint = "https://api.docsocr.com/api/v1/documents/birth-certificate";
// No engine could answer: nothing was charged, and a retry may succeed
string[] retryLater = ["EXTRACTION_BUSY", "EXTRACTION_TIMEOUT", "EXTRACTION_UNAVAILABLE"];
// Still in progress, too many requests, the service restarting
int[] retryStatus = [409, 429, 502, 503, 504];

using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(120) }; // above the API's 90 s extraction budget
http.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("DOCSOCR_API_KEY"));
var body = new JsonObject
{
    ["imageType"] = "url",
    ["imageUrl"] = "https://docsocr.com/samples/certidao-nascimento-exemplo.jpg",
    ["requestId"] = Guid.NewGuid().ToString(), // one id per document, the same on every retry
}.ToJsonString();

for (var attempt = 0; attempt < 5; attempt++)
{
    var backoff = TimeSpan.FromSeconds(1 << attempt); // seconds: 1, 2, 4, 8
    using var content = new StringContent(body, Encoding.UTF8, "application/json");
    HttpResponseMessage response;
    try
    {
        response = await http.PostAsync(Endpoint, content);
    }
    catch (Exception error) when (error is HttpRequestException or TaskCanceledException)
    {
        await Task.Delay(backoff); // a timeout or a dropped connection
        continue;
    }
    using (response)
    {
        var status = (int)response.StatusCode;
        var text = await response.Content.ReadAsStringAsync();
        var isJson = response.Content.Headers.ContentType?.MediaType == "application/json";
        using var answer = JsonDocument.Parse(isJson ? text : "{}");
        var root = answer.RootElement;
        var errorCode = root.TryGetProperty("errorCode", out var code) ? code.GetString() : "";

        if (status == 201 && root.TryGetProperty("success", out var ok) && ok.GetBoolean())
        {
            var name = root.GetProperty("data").GetProperty("dados_pessoais").GetProperty("nome_completo").GetString();
            Console.WriteLine($"{name} credits: {root.GetProperty("creditsCharged")}");
            return 0;
        }
        // Wait as long as the answer asks (retryAfter); a limit that resets
        // later, such as a daily quota, is not worth waiting for
        var wait = root.TryGetProperty("retryAfter", out var after) && after.ValueKind == JsonValueKind.Number
            ? TimeSpan.FromSeconds(after.GetInt32())
            : backoff;
        var retry = retryLater.Contains(errorCode) || retryStatus.Contains(status);
        if (retry && wait <= TimeSpan.FromMinutes(1))
        {
            await Task.Delay(wait);
            continue;
        }
        // 400 the body, 401 the key, 402 NOT_ENOUGH_CREDITS, 422 the image
        // (its errorCode says what to fix), DOCUMENT_NOT_RECOGNIZED: fix it, don't retry
        Console.Error.WriteLine($"{status} {errorCode} {text}");
        return 1;
    }
}
Console.Error.WriteLine("No answer after retries: try again later");
return 1;

Preços

Consulta o preço de uma extração em créditos, por motor e para o resizeImage. Não precisa de chave.

Prices.cs
// The price of an extraction, in credits, per engine and for resizeImage.
// A public endpoint: no key needed. Needs .NET 8+. Run: dotnet run Prices.cs (.NET 10)
using System.Text.Json;

using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
using var prices = JsonDocument.Parse(await http.GetStringAsync("https://api.docsocr.com/api/v1/documents/prices"));

foreach (var price in prices.RootElement.EnumerateObject())
{
    Console.WriteLine($"{price.Name}: {price.Value} credit(s)");
}

Pronto para começar?

Crie sua conta, receba créditos grátis e rode o primeiro exemplo com a sua chave.