diff --git a/EnvelopeGenerator.ReceiverUI/Models/AnnotationDto.cs b/EnvelopeGenerator.ReceiverUI/Models/AnnotationDto.cs
new file mode 100644
index 00000000..642cc6a9
--- /dev/null
+++ b/EnvelopeGenerator.ReceiverUI/Models/AnnotationDto.cs
@@ -0,0 +1,29 @@
+namespace EnvelopeGenerator.ReceiverUI.Models;
+
+///
+/// Represents a pre-assigned signature annotation position on a specific page.
+///
+/// Coordinate unit (X, Y): Hundredths of an inch (1/100 inch ? 2.83 PDF points),
+/// origin at the top-left corner of the page, both axes increase downward/rightward.
+/// This matches the DevExpress XtraReports coordinate system ().
+///
+/// Difference from PSPDFKit: Same origin (top-left) and direction, but PSPDFKit uses PDF points (1/72 inch).
+/// Convert: xDX = xPsPdf * (100.0 / 72.0)
+///
+/// Difference from GDPicture: GDPicture uses PDF points with bottom-left origin (PDF standard); Y is flipped.
+/// Convert: yDX = (pageHeightPt - yGD - elemHeightPt) * (100.0 / 72.0)
+///
+public record AnnotationDto
+{
+ /// Unique identifier of the annotation.
+ public long Id { get; init; }
+
+ /// 1-based page number within the document.
+ public int? Page { get; init; }
+
+ /// Horizontal position in hundredths of an inch from the left edge of the page.
+ public double? X { get; init; }
+
+ /// Vertical position in hundredths of an inch from the top edge of the page.
+ public double? Y { get; init; }
+}
diff --git a/EnvelopeGenerator.ReceiverUI/Program.cs b/EnvelopeGenerator.ReceiverUI/Program.cs
index 00b87dd5..2e54da86 100644
--- a/EnvelopeGenerator.ReceiverUI/Program.cs
+++ b/EnvelopeGenerator.ReceiverUI/Program.cs
@@ -16,6 +16,7 @@ builder.Services.Configure(opts =>
builder.Configuration.GetSection(ApiOptions.SectionName).Bind(opts));
builder.Services.AddScoped();
builder.Services.AddScoped();
+builder.Services.AddScoped();
builder.Services.AddDevExpressWebAssemblyBlazorReportViewer();
builder.Services.AddDevExpressWebAssemblyBlazorPdfViewer();
diff --git a/EnvelopeGenerator.ReceiverUI/Services/AnnotationService.cs b/EnvelopeGenerator.ReceiverUI/Services/AnnotationService.cs
new file mode 100644
index 00000000..5fde8210
--- /dev/null
+++ b/EnvelopeGenerator.ReceiverUI/Services/AnnotationService.cs
@@ -0,0 +1,32 @@
+using System.Net.Http.Json;
+using System.Text.Json;
+using EnvelopeGenerator.ReceiverUI.Models;
+using EnvelopeGenerator.ReceiverUI.Options;
+using Microsoft.Extensions.Options;
+
+namespace EnvelopeGenerator.ReceiverUI.Services;
+
+///
+/// Retrieves annotation positions from the API.
+/// The URL is composed as {BaseUrl}/api/Annotation/{envelopeKey}.
+/// During development, BaseUrl is empty so the request resolves to the
+/// YARP-proxied route on the same origin, which currently serves
+/// fake-data/annotations.json. To switch to real data, update the
+/// YARP route in yarp.json — no code change required.
+///
+public class AnnotationService(HttpClient http, IOptions apiOptions)
+{
+ private static readonly JsonSerializerOptions _jsonOptions = new(JsonSerializerDefaults.Web);
+
+ public async Task> GetAnnotationsAsync(string envelopeKey, CancellationToken cancel = default)
+ {
+ var url = $"{apiOptions.Value.BaseUrl}/api/Annotation/{Uri.EscapeDataString(envelopeKey)}";
+ var response = await http.GetAsync(url, cancel);
+
+ if (!response.IsSuccessStatusCode)
+ return [];
+
+ var result = await response.Content.ReadFromJsonAsync>(_jsonOptions, cancel);
+ return result ?? [];
+ }
+}