Skip to content

damianh/hubspot

Repository files navigation

HubSpot .NET Client & Mock Server

CI License .NET GitHub Stars

A comprehensive .NET library for interacting with HubSpot APIs.

Packages

Package Description NuGet Downloads
DamianH.HubSpot.KiotaClient Auto-generated HubSpot API client using Microsoft Kiota NuGet Downloads
DamianH.HubSpot.MockServer In-memory mock HubSpot server for testing without external dependencies NuGet Downloads
DamianH.HubSpot.Cli CLI tool for interacting with the HubSpot API NuGet Downloads

Quick Start

Using the HubSpot Client

using DamianH.HubSpot;

// Create a client with your access token
var client = new HubSpotClient("your-access-token");

// Work with CRM objects
var companies = await client.Crm.V3.Objects.Companies.GetAsync();
var contacts = await client.Crm.V3.Objects.Contacts.GetAsync();

// Create a new contact
var newContact = await client.Crm.V3.Objects.Contacts.PostAsync(new SimplePublicObjectInputForCreate 
{
    Properties = new Dictionary<string, string>
    {
        ["email"] = "test@example.com",
        ["firstname"] = "John",
        ["lastname"] = "Doe"
    }
});

Using the Mock Server in Tests

using DamianH.HubSpot.MockServer;

public class MyTests : IAsyncLifetime
{
    private HubSpotMockServer _mockServer;
    private HubSpotClient _client;

    public async Task InitializeAsync()
    {
        _mockServer = await HubSpotMockServer.StartNew();
        _client = new HubSpotClient("mock-token", _mockServer.BaseUri);
    }

    [Fact]
    public async Task CanCreateAndRetrieveContact()
    {
        // Create contact through mock server
        var created = await _client.Crm.V3.Objects.Contacts.PostAsync(new() 
        {
            Properties = new Dictionary<string, string> 
            { 
                ["email"] = "test@example.com" 
            }
        });
        
        // Retrieve it back
        var retrieved = await _client.Crm.V3.Objects.Contacts[created.Id].GetAsync();
        
        Assert.Equal("test@example.com", retrieved.Properties["email"]);
    }

    public async Task DisposeAsync() => await _mockServer.DisposeAsync();
}

Building & Testing

Prerequisites

  • .NET 10.0 SDK or later
  • PowerShell (for client generation)

Build the Solution

dotnet build hubspot.sln

Run Tests

dotnet test hubspot.sln

All tests should pass - the test suite validates both the mock server implementation and client functionality.

Regenerate Kiota Clients

When HubSpot updates their APIs, regenerate the client:

.\src\generate.ps1

Important: Never manually edit files marked with // <auto-generated/> - they will be overwritten during regeneration.

Supported APIs

The mock server implements comprehensive support for HubSpot APIs:

CRM APIs

  • Standard Objects: Companies, Contacts, Deals, Line Items, Products, Tickets, Quotes, Goals, Calls, Emails, Meetings, Notes, Tasks, Postal Mail, Communications
  • Custom Objects: Full CRUD + search support
  • Associations: Create, read, and manage associations between objects
  • Properties: Custom property definitions and management
  • Pipelines: Deal and ticket pipelines with stages
  • Owners: User and team management
  • Imports/Exports: Batch data operations

Marketing APIs

  • Marketing Events: Event management and tracking
  • Transactional Email: Send single emails
  • Marketing Emails: Campaign email management
  • Forms: Form submissions
  • Campaigns: Marketing campaign tracking

Conversations APIs

  • Visitor Identification: Track website visitors
  • Custom Channels: Custom messaging channels

Automation APIs

  • Workflows: Automation workflow management

CMS APIs

  • Blog Posts: Create and manage blog content
  • Blog Authors: Author profiles
  • Pages: Landing and site pages
  • Domains: Domain management
  • URL Redirects: Redirect rules
  • HubDB: Database tables
  • Source Code: File management
  • Site Search: Search configuration
  • Media Bridge: Media integration

Business Management

  • Webhooks: Subscribe to HubSpot events
  • Events: Custom event tracking
  • Files: File upload and management
  • Business Units: Multi-business unit support
  • Schemas: Custom object schemas
  • Timeline: Custom timeline events

Settings & Configuration

  • Account Info: Account details and configuration
  • User Provisioning: User management
  • Multicurrency: Currency settings
  • Tax Rates: Tax configuration

Extensions

  • Calling: Call integration
  • CRM Cards: Custom CRM cards
  • Video Conferencing: Meeting integration
  • Transcription: Call transcription

Mock Server Architecture

The mock server uses an in-memory repository pattern:

Key Components

  1. HubSpotMockServer: Main server class that hosts the ASP.NET Core web application
  2. ApiRoutes.*.cs: Partial classes containing route registrations for each API domain
  3. Repositories: In-memory stores for different entity types (thread-safe)
  4. API Models: DTOs matching HubSpot's API contracts

Design Principles

  • Stateful: All data persists for the lifetime of the server instance
  • Realistic: Mimics HubSpot's actual API behavior (validation, error responses, etc.)
  • Testable: Easy to spin up/down for isolated test scenarios
  • Extensible: Add new endpoints by extending ApiRoutes partial classes

Example: Adding a New Endpoint

// ApiRoutes.MyNewApi.cs
public partial class ApiRoutes
{
    public static void RegisterMyNewApi(WebApplication app)
    {
        var group = app.MapGroup("/my-api/v1");
        
        group.MapGet("/items", (MyRepository repo) => 
        {
            return Results.Ok(repo.GetAll());
        });
        
        group.MapPost("/items", (MyRepository repo, MyItem item) => 
        {
            var created = repo.Create(item);
            return Results.Created($"/my-api/v1/items/{created.Id}", created);
        });
    }
}

// In HubSpotMockServer.cs constructor:
ApiRoutes.RegisterMyNewApi(app);

Testing Strategy

The test suite covers:

  • All CRM standard objects (CRUD + search)
  • Custom objects and schemas
  • Associations between objects
  • Batch operations
  • Marketing emails and events
  • Webhooks and events
  • File operations
  • CMS functionality
  • Business unit support
  • Multi-version API support (V3, V202509, etc.)

Tests validate both:

  1. Mock server behavior (correct responses, validation, etc.)
  2. Generated Kiota client compatibility

Authentication

The mock server accepts any authentication token - it doesn't validate tokens. This allows for easy testing without real HubSpot credentials.

For production use with the real HubSpot API:

var client = new HubSpotClient("your-production-access-token");

Related Links

Tips & Tricks

Debugging Tests

The mock server runs on a random port for each test to avoid conflicts. Access the URI via:

Console.WriteLine($"Mock server running at: {_mockServer.Uri}");

Resetting State Between Tests

Each test should create its own HubSpotMockServer instance to ensure isolation:

public async Task InitializeAsync()
{
    _mockServer = await HubSpotMockServer.StartNew();
}

Working with Search

The mock server supports HubSpot's search API with filters, sorting, and pagination:

var searchRequest = new PublicObjectSearchRequest
{
    FilterGroups = new List<FilterGroup>
    {
        new FilterGroup
        {
            Filters = new List<Filter>
            {
                new Filter { PropertyName = "email", Operator = "EQ", Value = "test@example.com" }
            }
        }
    }
};

var results = await client.Crm.V3.Objects.Contacts.Search.PostAsync(searchRequest);

Handling Associations

Create associations between objects:

// Associate a contact with a company
await client.Crm.V4.Objects.Contacts[contactId].Associations.Companies[companyId]
    .PutAsync(new[] 
    { 
        new AssociationSpec { AssociationTypeId = 1 } // contact_to_company
    });

About

HubSpot client library generated with Kiota

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages