Skip to content

Commit 1516137

Browse files
Update Contacts, Deprecate Audiences (#92)
1 parent c40778b commit 1516137

21 files changed

Lines changed: 186 additions & 189 deletions

src/Resend.Webhooks/ContactEventData.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ public class ContactEventData : IWebhookData
1010
public Guid ContactId { get; set; }
1111

1212
/// <summary />
13-
[JsonPropertyName( "audience_id" )]
14-
public Guid AudienceId { get; set; }
13+
[JsonPropertyName( "segment_ids" )]
14+
[JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
15+
public List<Guid>? SegmentIds { get; set; }
1516

1617
/// <summary />
1718
[JsonPropertyName( "created_at" )]

src/Resend/Broadcast.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ public class Broadcast
1919
public string? DisplayName { get; set; }
2020

2121
/// <summary>
22-
/// Audience identifier.
22+
/// Segment identifier.
2323
/// </summary>
24-
[JsonPropertyName( "audience_id" )]
25-
public Guid AudienceId { get; set; }
24+
[JsonPropertyName( "segment_id" )]
25+
public Guid SegmentId { get; set; }
2626

2727
/// <summary>
2828
/// From.

src/Resend/BroadcastData.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ public class BroadcastData
1313
public string? DisplayName { get; set; }
1414

1515
/// <summary>
16-
/// Audience identifier.
16+
/// Segment identifier.
1717
/// </summary>
18-
[JsonPropertyName( "audience_id" )]
19-
public Guid AudienceId { get; set; }
18+
[JsonPropertyName( "segment_id" )]
19+
public Guid SegmentId { get; set; }
2020

2121
/// <summary>
2222
/// Sender email address.

src/Resend/BroadcastUpdateData.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ public class BroadcastUpdateData
1313
public string? DisplayName { get; set; }
1414

1515
/// <summary>
16-
/// Audience identifier.
16+
/// Segment identifier.
1717
/// </summary>
18-
[JsonPropertyName( "audience_id" )]
18+
[JsonPropertyName( "segment_id" )]
1919
[JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
20-
public Guid? AudienceId { get; set; }
20+
public Guid? SegmentId { get; set; }
2121

2222
/// <summary>
2323
/// Sender email address.

src/Resend/Contact.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,11 @@ public class Contact
4646
[JsonPropertyName( "unsubscribed" )]
4747
[JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
4848
public bool? IsUnsubscribed { get; set; }
49-
}
49+
50+
/// <summary>
51+
/// Key/value custom properties for the contact.
52+
/// </summary>
53+
[JsonPropertyName( "properties" )]
54+
[JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
55+
public Dictionary<string,string>? Properties { get; set; }
56+
}

src/Resend/ContactData.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,11 @@ public class ContactData
3636
[JsonPropertyName( "unsubscribed" )]
3737
[JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
3838
public bool? IsUnsubscribed { get; set; }
39+
40+
/// <summary>
41+
/// Key/value custom properties for the contact.
42+
/// </summary>
43+
[JsonPropertyName( "properties" )]
44+
[JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
45+
public Dictionary<string, string>? Properties { get; set; }
3946
}

src/Resend/IResend.cs

Lines changed: 16 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ public interface IResend
368368
/// Task.
369369
/// </returns>
370370
/// <see href="https://resend.com/docs/api-reference/audiences/create-audience" />
371+
[Obsolete( "Use Segments instead" )]
371372
Task<ResendResponse<Guid>> AudienceAddAsync( string name, CancellationToken cancellationToken = default );
372373

373374
/// <summary>
@@ -383,6 +384,7 @@ public interface IResend
383384
/// List of Audience.
384385
/// </returns>
385386
/// <see href="https://resend.com/docs/api-reference/audiences/get-audience" />
387+
[Obsolete( "Use Segments instead" )]
386388
Task<ResendResponse<Audience>> AudienceRetrieveAsync( Guid audienceId, CancellationToken cancellationToken = default );
387389

388390
/// <summary>
@@ -398,6 +400,7 @@ public interface IResend
398400
/// Task.
399401
/// </returns>
400402
/// <see href="https://resend.com/docs/api-reference/audiences/delete-audience" />
403+
[Obsolete( "Use Segments instead" )]
401404
Task<ResendResponse> AudienceDeleteAsync( Guid audienceId, CancellationToken cancellationToken = default );
402405

403406
/// <summary>
@@ -410,18 +413,16 @@ public interface IResend
410413
/// A list of Audience.
411414
/// </returns>
412415
/// <see href="https://resend.com/docs/api-reference/audiences/list-audiences" />
416+
[Obsolete( "Use Segments instead" )]
413417
Task<ResendResponse<List<Audience>>> AudienceListAsync( CancellationToken cancellationToken = default );
414418

415419
#endregion
416420

417421
#region Contacts
418422

419423
/// <summary>
420-
/// Create a contact inside an audience.
424+
/// Create a contact.
421425
/// </summary>
422-
/// /// <param name="audienceId">
423-
/// Audience identifier.
424-
/// </param>
425426
/// <param name="data">
426427
/// Contact data.
427428
/// </param>
@@ -432,14 +433,11 @@ public interface IResend
432433
/// Contact Id.
433434
/// </returns>
434435
/// <see href="https://resend.com/docs/api-reference/contacts/create-contact" />
435-
Task<ResendResponse<Guid>> ContactAddAsync( Guid audienceId, ContactData data, CancellationToken cancellationToken = default );
436+
Task<ResendResponse<Guid>> ContactAddAsync( ContactData data, CancellationToken cancellationToken = default );
436437

437438
/// <summary>
438-
/// Retrieve a single contact from an audience.
439+
/// Retrieve a contact.
439440
/// </summary>
440-
/// <param name="audienceId">
441-
/// Audience identifier.
442-
/// </param>
443441
/// <param name="contactId">
444442
/// Contact identifier.
445443
/// </param>
@@ -450,14 +448,11 @@ public interface IResend
450448
/// A Contact.
451449
/// </returns>
452450
/// <see href="https://resend.com/docs/api-reference/contacts/get-contact" />
453-
Task<ResendResponse<Contact>> ContactRetrieveAsync( Guid audienceId, Guid contactId, CancellationToken cancellationToken = default );
451+
Task<ResendResponse<Contact>> ContactRetrieveAsync( Guid contactId, CancellationToken cancellationToken = default );
454452

455453
/// <summary>
456454
/// Retrieve a single contact from an audience using email address.
457455
/// </summary>
458-
/// <param name="audienceId">
459-
/// Audience identifier.
460-
/// </param>
461456
/// <param name="email">
462457
/// Contact email.
463458
/// </param>
@@ -468,14 +463,11 @@ public interface IResend
468463
/// A Contact.
469464
/// </returns>
470465
/// <see href="https://resend.com/docs/api-reference/contacts/get-contact" />
471-
Task<ResendResponse<Contact>> ContactRetrieveByEmailAsync( Guid audienceId, string email, CancellationToken cancellationToken = default );
466+
Task<ResendResponse<Contact>> ContactRetrieveByEmailAsync( string email, CancellationToken cancellationToken = default );
472467

473468
/// <summary>
474469
/// Update an existing contact.
475470
/// </summary>
476-
/// <param name="audienceId">
477-
/// Audience identifier.
478-
/// </param>
479471
/// <param name="contactId">
480472
/// Contact identifier.
481473
/// </param>
@@ -489,14 +481,11 @@ public interface IResend
489481
/// Task.
490482
/// </returns>
491483
/// <see href="https://resend.com/docs/api-reference/contacts/update-contact" />
492-
Task<ResendResponse> ContactUpdateAsync( Guid audienceId, Guid contactId, ContactData data, CancellationToken cancellationToken = default );
484+
Task<ResendResponse> ContactUpdateAsync( Guid contactId, ContactData data, CancellationToken cancellationToken = default );
493485

494486
/// <summary>
495487
/// Update an existing contact.
496488
/// </summary>
497-
/// <param name="audienceId">
498-
/// Audience identifier.
499-
/// </param>
500489
/// <param name="email">
501490
/// Email.
502491
/// </param>
@@ -510,14 +499,11 @@ public interface IResend
510499
/// Task.
511500
/// </returns>
512501
/// <see href="https://resend.com/docs/api-reference/contacts/update-contact" />
513-
Task<ResendResponse> ContactUpdateByEmailAsync( Guid audienceId, string email, ContactData data, CancellationToken cancellationToken = default );
502+
Task<ResendResponse> ContactUpdateByEmailAsync( string email, ContactData data, CancellationToken cancellationToken = default );
514503

515504
/// <summary>
516505
/// Remove a contact.
517506
/// </summary>
518-
/// <param name="audienceId">
519-
/// Audience identifier.
520-
/// </param>
521507
/// <param name="contactId">
522508
/// Contact identifier.
523509
/// </param>
@@ -528,14 +514,11 @@ public interface IResend
528514
/// Task.
529515
/// </returns>
530516
/// <see href="https://resend.com/docs/api-reference/contacts/delete-contact" />
531-
Task<ResendResponse> ContactDeleteAsync( Guid audienceId, Guid contactId, CancellationToken cancellationToken = default );
517+
Task<ResendResponse> ContactDeleteAsync( Guid contactId, CancellationToken cancellationToken = default );
532518

533519
/// <summary>
534520
/// Remove a contact by their email address.
535521
/// </summary>
536-
/// <param name="audienceId">
537-
/// Audience identifier.
538-
/// </param>
539522
/// <param name="email">
540523
/// Email address of the contact.
541524
/// </param>
@@ -546,14 +529,11 @@ public interface IResend
546529
/// Task
547530
/// </returns>
548531
/// <see href="https://resend.com/docs/api-reference/contacts/delete-contact" />
549-
Task<ResendResponse> ContactDeleteByEmailAsync( Guid audienceId, string email, CancellationToken cancellationToken = default );
532+
Task<ResendResponse> ContactDeleteByEmailAsync( string email, CancellationToken cancellationToken = default );
550533

551534
/// <summary>
552-
/// List contacts from an audience.
535+
/// List contacts.
553536
/// </summary>
554-
/// <param name="audienceId">
555-
/// Audience identifier.
556-
/// </param>
557537
/// <param name="query">
558538
/// Paginated query.
559539
/// </param>
@@ -564,10 +544,10 @@ public interface IResend
564544
/// List of contacts.
565545
/// </returns>
566546
/// <see href="https://resend.com/docs/api-reference/contacts/list-contacts" />
567-
Task<ResendResponse<PaginatedResult<Contact>>> ContactListAsync( Guid audienceId, PaginatedQuery? query = null, CancellationToken cancellationToken = default );
547+
Task<ResendResponse<PaginatedResult<Contact>>> ContactListAsync( PaginatedQuery? query = null, CancellationToken cancellationToken = default );
568548

569549
/// <summary>
570-
/// Lists contact segments,.
550+
/// Lists segments for a contact.
571551
/// </summary>
572552
/// <param name="contactId">Contact identifier.</param>
573553
/// <param name="query">Paginated query.</param>

src/Resend/ResendClient.Contacts.cs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
using Microsoft.AspNetCore.WebUtilities;
22
using Resend.Payloads;
33
using System.Net.Http.Json;
4-
using static System.Runtime.InteropServices.JavaScript.JSType;
54

65
namespace Resend;
76

87
public partial class ResendClient
98
{
109
/// <inheritdoc/>
11-
public Task<ResendResponse<Guid>> ContactAddAsync( Guid audienceId, ContactData data, CancellationToken cancellationToken = default )
10+
public Task<ResendResponse<Guid>> ContactAddAsync( ContactData data, CancellationToken cancellationToken = default )
1211
{
1312
if ( data.Email == null )
1413
throw new ArgumentException( "Email must be non-null when creating contact", nameof( data ) + ".Email" );
1514

16-
var path = $"/audiences/{audienceId}/contacts";
15+
var path = $"/contacts";
1716
var req = new HttpRequestMessage( HttpMethod.Post, path );
1817
req.Content = JsonContent.Create( data );
1918

@@ -22,29 +21,29 @@ public partial class ResendClient
2221

2322

2423
/// <inheritdoc/>
25-
public Task<ResendResponse<Contact>> ContactRetrieveAsync( Guid audienceId, Guid contactId, CancellationToken cancellationToken = default )
24+
public Task<ResendResponse<Contact>> ContactRetrieveAsync( Guid contactId, CancellationToken cancellationToken = default )
2625
{
27-
var path = $"/audiences/{audienceId}/contacts/{contactId}";
26+
var path = $"/contacts/{contactId}";
2827
var req = new HttpRequestMessage( HttpMethod.Get, path );
2928

3029
return Execute<Contact, Contact>( req, ( x ) => x, cancellationToken );
3130
}
3231

3332

3433
/// <inheritdoc/>
35-
public Task<ResendResponse<Contact>> ContactRetrieveByEmailAsync( Guid audienceId, string email, CancellationToken cancellationToken = default )
34+
public Task<ResendResponse<Contact>> ContactRetrieveByEmailAsync( string email, CancellationToken cancellationToken = default )
3635
{
37-
var path = $"/audiences/{audienceId}/contacts/{email}";
36+
var path = $"/contacts/{email}";
3837
var req = new HttpRequestMessage( HttpMethod.Get, path );
3938

4039
return Execute<Contact, Contact>( req, ( x ) => x, cancellationToken );
4140
}
4241

4342

4443
/// <inheritdoc/>
45-
public Task<ResendResponse> ContactUpdateAsync( Guid audienceId, Guid contactId, ContactData data, CancellationToken cancellationToken = default )
44+
public Task<ResendResponse> ContactUpdateAsync( Guid contactId, ContactData data, CancellationToken cancellationToken = default )
4645
{
47-
var path = $"/audiences/{audienceId}/contacts/{contactId}";
46+
var path = $"/contacts/{contactId}";
4847
var req = new HttpRequestMessage( HttpMethod.Patch, path );
4948
req.Content = JsonContent.Create( data );
5049

@@ -53,9 +52,9 @@ public partial class ResendClient
5352

5453

5554
/// <inheritdoc/>
56-
public Task<ResendResponse> ContactUpdateByEmailAsync( Guid audienceId, string email, ContactData data, CancellationToken cancellationToken = default )
55+
public Task<ResendResponse> ContactUpdateByEmailAsync( string email, ContactData data, CancellationToken cancellationToken = default )
5756
{
58-
var path = $"/audiences/{audienceId}/contacts/{email}";
57+
var path = $"/contacts/{email}";
5958
var req = new HttpRequestMessage( HttpMethod.Patch, path );
6059
req.Content = JsonContent.Create( data );
6160

@@ -64,29 +63,29 @@ public partial class ResendClient
6463

6564

6665
/// <inheritdoc/>
67-
public Task<ResendResponse> ContactDeleteAsync( Guid audienceId, Guid contactId, CancellationToken cancellationToken = default )
66+
public Task<ResendResponse> ContactDeleteAsync( Guid contactId, CancellationToken cancellationToken = default )
6867
{
69-
var path = $"/audiences/{audienceId}/contacts/{contactId}";
68+
var path = $"/contacts/{contactId}";
7069
var req = new HttpRequestMessage( HttpMethod.Delete, path );
7170

7271
return Execute( req, cancellationToken );
7372
}
7473

7574

7675
/// <inheritdoc/>
77-
public Task<ResendResponse> ContactDeleteByEmailAsync( Guid audienceId, string email, CancellationToken cancellationToken = default )
76+
public Task<ResendResponse> ContactDeleteByEmailAsync( string email, CancellationToken cancellationToken = default )
7877
{
79-
var path = $"/audiences/{audienceId}/contacts/{email}";
78+
var path = $"/contacts/{email}";
8079
var req = new HttpRequestMessage( HttpMethod.Delete, path );
8180

8281
return Execute( req, cancellationToken );
8382
}
8483

8584

8685
/// <inheritdoc/>
87-
public Task<ResendResponse<PaginatedResult<Contact>>> ContactListAsync( Guid audienceId, PaginatedQuery? query = null, CancellationToken cancellationToken = default )
86+
public Task<ResendResponse<PaginatedResult<Contact>>> ContactListAsync( PaginatedQuery? query = null, CancellationToken cancellationToken = default )
8887
{
89-
var baseUrl = $"/audiences/{audienceId}/contacts";
88+
var baseUrl = $"/contacts";
9089
var url = baseUrl;
9190

9291
if ( query != null )

src/Resend/ResendException.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ public bool IsTransient
5151
{
5252
return this.ErrorType switch
5353
{
54-
ErrorType.MissingApiKey => true,
55-
54+
ErrorType.MonthlyQuotaExceeded => true,
5655
ErrorType.DailyQuotaExceeded => true,
5756
ErrorType.RateLimitExceeded => true,
5857
ErrorType.HttpSendFailed => true,

0 commit comments

Comments
 (0)