Skip to content

Add webhook event models and documentation - #36

Merged
teesofttech merged 2 commits into
mainfrom
feature/32-webhook-models
Jun 14, 2026
Merged

Add webhook event models and documentation#36
teesofttech merged 2 commits into
mainfrom
feature/32-webhook-models

Conversation

@teesofttech

@teesofttech teesofttech commented Jun 14, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add TermiiWebhookEvent for receiver-side webhook payload deserialization
  • Preserve unknown webhook fields through JsonExtensionData
  • Add deserialization unit tests for delivered and failed report-style payloads
  • Add ASP.NET Core README example and update API coverage

Verification note

  • I did not find an authoritative current Termii webhook payload example in the docs or Postman collection.
  • The model intentionally covers common delivery/report fields while preserving unknown fields for account-specific payloads.

Validation

  • dotnet restore Termii.SDK.sln
  • dotnet build Termii.SDK.sln --configuration Release --no-restore
  • dotnet test tests/Termii.Tests/Termii.Tests.csproj --configuration Release --no-build --logger "trx;LogFileName=unit-tests.trx"
  • dotnet test tests/Termii.IntegrationTests/Termii.IntegrationTests.csproj --configuration Release --no-build --logger "trx;LogFileName=integration-tests.trx"
  • dotnet pack src/Termii/Termii.csproj --configuration Release --no-build --output artifacts/packages -p:UseSharedCompilation=false -p:BuildInParallel=false -p:MSBuildNodeReuse=false

Closes #32

Summary by CodeRabbit

  • New Features

    • Added webhook event support enabling ASP.NET Core applications to receive Termii delivery and report callbacks.
  • Documentation

    • Updated API coverage status to reflect webhook event implementation.
    • Added webhook integration guide with code examples to README.

Copilot AI review requested due to automatic review settings June 14, 2026 02:44
@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@teesofttech, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 55 minutes and 25 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1a302cd4-2ea8-4a78-a837-f0aff3e6ea52

📥 Commits

Reviewing files that changed from the base of the PR and between 20f4cc4 and 3555faf.

📒 Files selected for processing (2)
  • README.md
  • src/Termii/Termii.csproj
📝 Walkthrough

Walkthrough

Adds a TermiiWebhookEvent sealed DTO with nullable JSON-mapped properties and a JsonExtensionData dictionary. Two XUnit tests cover deserialization of delivery and failed-report payloads. The README gains a webhook usage section, and docs/API_COVERAGE.md marks webhook events as implemented.

Changes

Webhook Event Model and Documentation

Layer / File(s) Summary
TermiiWebhookEvent DTO and deserialization tests
src/Termii/Webhooks/TermiiWebhookEvent.cs, tests/Termii.Tests/TermiiWebhookEventTests.cs
Defines TermiiWebhookEvent as a public sealed class with JsonPropertyName-mapped nullable string/decimal properties and a [JsonExtensionData] AdditionalData dictionary. Tests validate delivery-report and failed-report JSON payloads deserialize correctly, including decimal-from-string coercion and unknown fields captured in AdditionalData.
README webhook section and API coverage update
README.md, docs/API_COVERAGE.md
Adds a Webhooks section to the README with a MapPost ASP.NET Core handler sample, removes the now-implemented "Webhook event models" deferred bullet, and reclassifies the "Insights | Webhook events and reports" coverage row from Deferred to Implemented.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 A webhook arrives with a knock at the door,
I mapped all its fields — and then a few more!
The AdditionalData catches what slips through,
Delivered or failed, I'll parse it for you.
With tests and a README, the story is told —
This rabbit's SDK grows better than gold! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and clearly describes the main change: adding webhook event models and documentation.
Linked Issues check ✅ Passed The PR fully implements all coding objectives from #32: adds TermiiWebhookEvent model with deserialization support, includes XUnit tests for delivery/failed reports, adds ASP.NET Core endpoint example in README, and updates API coverage documentation.
Out of Scope Changes check ✅ Passed All changes are directly aligned with #32 objectives: TermiiWebhookEvent model, deserialization tests, README webhook documentation, and API coverage updates—no out-of-scope changes detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/32-webhook-models

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
tests/Termii.Tests/TermiiWebhookEventTests.cs (1)

49-76: 💤 Low value

Consider verifying AdditionalData behavior when no unknown fields are present.

The second test deserializes a payload with no unknown JSON properties but doesn't assert the state of AdditionalData. Adding an assertion that it is null or empty would improve test completeness and document the expected behavior.

🧪 Optional assertion to add
     Assert.Equal("3001", webhookEvent.ErrorCode);
     Assert.Equal("Insufficient balance", webhookEvent.ErrorMessage);
     Assert.Equal("2026-06-14 09:05:00", webhookEvent.DoneDate);
+    Assert.True(webhookEvent.AdditionalData == null || webhookEvent.AdditionalData.Count == 0);
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Termii.Tests/TermiiWebhookEventTests.cs` around lines 49 - 76, The test
CanDeserializeFailedReportPayload deserializes a webhook event payload but does
not verify the state of the AdditionalData property when no unknown JSON fields
are present. Add an assertion after the existing Assert.Equal statements to
verify that AdditionalData is either null or empty, ensuring the test documents
the expected behavior for this scenario and improves test completeness.
src/Termii/Webhooks/TermiiWebhookEvent.cs (2)

6-70: ⚡ Quick win

Consider adding XML documentation for the public webhook event model.

The TermiiWebhookEvent class is a public API surface without XML documentation comments. Given that webhook payload structures can vary (as noted in the PR objectives), concise XML docs explaining the purpose of the class, the role of AdditionalData, and the meaning of key properties would help SDK consumers understand how to use this model effectively.

📝 Example documentation pattern
+/// <summary>
+/// Represents a webhook event payload sent by Termii for delivery reports and status updates.
+/// Webhook payload structures may vary by event type and account configuration.
+/// Unknown fields are captured in <see cref="AdditionalData"/>.
+/// </summary>
 public sealed class TermiiWebhookEvent
 {
+    /// <summary>
+    /// Gets or sets the event type (e.g., "message.status").
+    /// </summary>
     [JsonPropertyName("event")]
     public string? Event { get; set; }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Termii/Webhooks/TermiiWebhookEvent.cs` around lines 6 - 70, Add XML
documentation comments to the TermiiWebhookEvent class to improve API surface
documentation for SDK consumers. Add a summary comment above the class
definition explaining its purpose as a webhook event model, add documentation to
the AdditionalData property clarifying its role in handling dynamic payload
fields, and add summary comments to key properties (Event, Type, Status,
MessageId, To, From, Amount, ErrorCode, ErrorMessage, and timestamp properties
like CreatedAt, DeliveredAt, etc.) to explain their meaning within the webhook
payload context. This will help developers understand the structure and usage of
the webhook event model when integrating with the SDK.

8-67: 💤 Low value

Consider using init-only property setters for immutability.

The properties currently use public set, which allows mutation after deserialization. Using init setters would provide compile-time immutability guarantees while still supporting JSON deserialization.

♻️ Optional refactor to init-only setters
 [JsonPropertyName("event")]
-public string? Event { get; set; }
+public string? Event { get; init; }

 [JsonPropertyName("type")]
-public string? Type { get; set; }
+public string? Type { get; init; }

 // Apply to all properties...
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Termii/Webhooks/TermiiWebhookEvent.cs` around lines 8 - 67, The
TermiiWebhookEvent class properties currently use public setters which allow
mutation after deserialization. Replace `{ get; set; }` with `{ get; init; }`
for all properties in the class (Event, Type, MessageId, MessageIdString,
Status, To, From, Sender, Receiver, Channel, Network, Message, Amount,
ErrorCode, ErrorMessage, CreatedAt, UpdatedAt, SentAt, DeliveredAt, DoneDate) to
enforce compile-time immutability while maintaining JSON deserialization
compatibility.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/Termii/Webhooks/TermiiWebhookEvent.cs`:
- Around line 6-70: Add XML documentation comments to the TermiiWebhookEvent
class to improve API surface documentation for SDK consumers. Add a summary
comment above the class definition explaining its purpose as a webhook event
model, add documentation to the AdditionalData property clarifying its role in
handling dynamic payload fields, and add summary comments to key properties
(Event, Type, Status, MessageId, To, From, Amount, ErrorCode, ErrorMessage, and
timestamp properties like CreatedAt, DeliveredAt, etc.) to explain their meaning
within the webhook payload context. This will help developers understand the
structure and usage of the webhook event model when integrating with the SDK.
- Around line 8-67: The TermiiWebhookEvent class properties currently use public
setters which allow mutation after deserialization. Replace `{ get; set; }` with
`{ get; init; }` for all properties in the class (Event, Type, MessageId,
MessageIdString, Status, To, From, Sender, Receiver, Channel, Network, Message,
Amount, ErrorCode, ErrorMessage, CreatedAt, UpdatedAt, SentAt, DeliveredAt,
DoneDate) to enforce compile-time immutability while maintaining JSON
deserialization compatibility.

In `@tests/Termii.Tests/TermiiWebhookEventTests.cs`:
- Around line 49-76: The test CanDeserializeFailedReportPayload deserializes a
webhook event payload but does not verify the state of the AdditionalData
property when no unknown JSON fields are present. Add an assertion after the
existing Assert.Equal statements to verify that AdditionalData is either null or
empty, ensuring the test documents the expected behavior for this scenario and
improves test completeness.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e7123bb1-53c8-401b-8050-ad6ffabaf905

📥 Commits

Reviewing files that changed from the base of the PR and between 1d08d7d and 20f4cc4.

📒 Files selected for processing (4)
  • README.md
  • docs/API_COVERAGE.md
  • src/Termii/Webhooks/TermiiWebhookEvent.cs
  • tests/Termii.Tests/TermiiWebhookEventTests.cs

@teesofttech
teesofttech merged commit 6866752 into main Jun 14, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add webhook event models and documentation

2 participants