Skip to main content

Cloud REST with C# and .NET

Use HttpClient with the experimental Cloud API; no VisionScan NuGet scanning package is published.

Status
Experimental
Integration
Cloud REST client
Distribution
HTTP API
Version
0.1.0-RC4

Prerequisites

  • .NET 8 or newer
  • VISIONSCAN_CLOUD_URL
  • VISIONSCAN_ACCESS_TOKEN
  • A supported image file

1. Use the framework HTTP client

Use the framework HTTP client
dotnet new console --framework net8.0

No VisionScan NuGet dependency is required for the REST contract.

2. Configure HttpClient

Configure HttpClient
using var client = new HttpClient { BaseAddress = new Uri(cloudUrl), Timeout = TimeSpan.FromSeconds(30) };
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

Use IHttpClientFactory in long-lived ASP.NET applications.

3. Upload and submit

Upload and submit
var upload = await PostAsync<UploadResponse>(client, "/v1/uploads", new { idempotencyKey = Guid.NewGuid(), contentBase64 = Convert.ToBase64String(image), contentType = "image/png" });
var job = await PostAsync<JobResponse>(client, "/v1/jobs", new { idempotencyKey = Guid.NewGuid(), uploadIds = new[] { upload.uploadId }, profile = "still-image-dense" });
var status = await client.GetFromJsonAsync<JobStatus>($"/v1/jobs/{job.jobId}");

EnsureSuccessStatusCode before deserializing each response.

Errors and recovery

ConditionResolution
Deserialization returns nullPreserve the HTTP status and structured error body; do not turn a malformed response into an empty result.
409 idempotency conflictUse the original payload or issue a new key for changed content.

Production checklist

  • Use IHttpClientFactory
  • Set bounded timeouts and cancellation
  • Redact authorization headers
  • Do not claim a native .NET SDK

Public contract reference

These are the callable methods and HTTP operations used by this guide. Inputs, results, lifecycle rules, and denial behavior are part of the versioned customer contract.

Cloud upload contract

Upload bytes are authenticated, bounded, MIME-checked, idempotent, and tenant-scoped.

POST /v1/uploads

http

Persist one validated image and return a tenant-scoped upload identifier.

Inputs for POST /v1/uploads
InputTypeRequiredMeaning
AuthorizationBearer tokenYesProduction RS256 token with bounded time claims and cloud-scan entitlement.
idempotencyKeyUUID/stringYesTenant-scoped key reused only for an identical retry.
contentBase64base64 stringYesLocally bounded PNG, JPEG, or WebP bytes.
contentTypestringYesimage/png, image/jpeg, or image/webp matching the file magic bytes.
Result
2xx JSON containing uploadId and non-sensitive upload metadata.
Lifecycle
Upload before creating a job; retain the idempotency key for retries of the same bytes.
Trust boundary
Tenant and site come only from the verified token; request bodies cannot override tenant scope.
Failure behavior
  • 401/403 for invalid or unentitled identity.
  • 409 for a reused key with different content.
  • 4xx for invalid MIME, magic bytes, base64, or size; 429 for quota limits.

Cloud job creation contract

A job references same-tenant uploads and selects a bounded scan profile.

POST /v1/jobs

http

Create an asynchronous scan job from one or more previously accepted uploads.

Inputs for POST /v1/jobs
InputTypeRequiredMeaning
idempotencyKeyUUID/stringYesTenant-scoped key for identical job retries.
uploadIdsstring[]YesExisting upload IDs owned by the authenticated tenant and site.
profilestringYesAn allowlisted profile such as still-image-dense.
callbackHTTPS URLNoOptional policy-validated callback; production delivery requires the documented callback controls.
Result
2xx JSON containing jobId, queued status, and correlation metadata.
Lifecycle
Create after uploads succeed, then poll status until completed or failed.
Trust boundary
Callbacks reject non-HTTPS and non-global destinations, pin validated addresses, follow no redirects, and HMAC-sign payloads.
Failure behavior
  • Cross-tenant or unknown uploads are denied.
  • 409 reports idempotency conflict; 429 reports quota pressure; invalid profiles fail validation.

Cloud job status contract

Status retrieval distinguishes completed, failed, and unavailable-engine outcomes from an empty scan.

GET /v1/jobs/{jobId}

http

Read the authenticated tenant's job state, receipt, structured error, and callback delivery state.

Inputs for GET /v1/jobs/{jobId}
InputTypeRequiredMeaning
jobIdpath stringYesThe job identifier returned by POST /v1/jobs.
AuthorizationBearer tokenYesThe same tenant/site scope that owns the job.
Result
JSON status that becomes completed or failed; completed identity evidence remains GTIN-first and preserves review-required OCR provenance.
Lifecycle
Poll with bounded backoff and stop on a terminal state.
Trust boundary
Do not log bearer tokens, encoded images, or sensitive receipt payloads; retain only non-sensitive correlation metadata.
Failure behavior
  • Cross-tenant and unknown identifiers do not expose another tenant's data.
  • ENGINE_ADAPTER_UNAVAILABLE is a failed job, not a successful scan with zero observations.
  • Unknown response shapes fail closed.

Review the release support matrix before deployment. Support status and contract failure behavior remain authoritative even when an example is copied.