Skip to content

lunogram/go-sdk

Repository files navigation

Lunogram Go SDK

Go Reference

Go client library for the Lunogram Client API. Manage user profiles, organizations, events, and scheduled resources from any Go application.

Installation

go get github.com/lunogram/go-sdk

Requires Go 1.22 or later.

Quick start

package main

import (
	"context"
	"fmt"
	"log"

	lunogram "github.com/lunogram/go-sdk"
)

func main() {
	client := lunogram.NewClient("your-api-key")
	ctx := context.Background()

	user, err := client.UpsertUser(ctx, &lunogram.UpsertUserRequest{
		Identifier: []lunogram.ExternalID{
			{ExternalID: "user_123"},
		},
		Email: lunogram.String("jane@example.com"),
		Data: map[string]any{
			"first_name": "Jane",
			"plan":       "pro",
		},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Upserted user:", user.ID)
}

Client options

// Custom base URL (e.g. for self-hosted or staging environments)
client := lunogram.NewClient(apiKey, lunogram.WithBaseURL("https://custom.lunogram.io"))

// Custom HTTP client
client := lunogram.NewClient(apiKey, lunogram.WithHTTPClient(&http.Client{
	Timeout:   10 * time.Second,
	Transport: myTransport,
}))

// Custom timeout (applies to the default HTTP client)
client := lunogram.NewClient(apiKey, lunogram.WithTimeout(10*time.Second))

Users

Upsert a user

Create a new user or update an existing one. Users are matched by their external identifiers.

user, err := client.UpsertUser(ctx, &lunogram.UpsertUserRequest{
	Identifier: []lunogram.ExternalID{
		{ExternalID: "user_123"},
	},
	Email:    lunogram.String("jane@example.com"),
	Phone:    lunogram.String("+31612345678"),
	Timezone: lunogram.String("Europe/Amsterdam"),
	Locale:   lunogram.String("nl-NL"),
	Data: map[string]any{
		"first_name":    "Jane",
		"plan":          "enterprise",
	},
})

Delete a user

err := client.DeleteUser(ctx, &lunogram.DeleteUserRequest{
	Identifier: []lunogram.ExternalID{
		{ExternalID: "user_123"},
	},
})

Post user events

Send events that can trigger journeys or update virtual lists. Events are processed asynchronously.

err := client.PostUserEvents(ctx, []lunogram.Event{
	{
		Name: "purchase_completed",
		Identifier: []lunogram.ExternalID{
			{ExternalID: "user_123"},
		},
		Data: map[string]any{
			"product_id": "prod_789",
			"amount":     99.99,
		},
	},
})

You can also target events at users matching specific data attributes instead of an identifier:

err := client.PostUserEvents(ctx, []lunogram.Event{
	{
		Name:  "feature_announcement",
		Match: map[string]any{"plan": "enterprise"},
		Data:  map[string]any{"feature": "advanced_analytics"},
	},
})

Organizations

Upsert an organization

org, err := client.UpsertOrganization(ctx, &lunogram.UpsertOrganizationRequest{
	Identifier: []lunogram.ExternalID{
		{ExternalID: "org_456"},
	},
	Name: lunogram.String("Acme Corp"),
	Data: map[string]any{
		"industry": "technology",
		"size":     "enterprise",
	},
})

Delete an organization

Deleting an organization also removes all its user memberships.

err := client.DeleteOrganization(ctx, &lunogram.DeleteOrganizationRequest{
	Identifier: []lunogram.ExternalID{
		{ExternalID: "org_456"},
	},
})

Add a user to an organization

err := client.AddOrganizationUser(ctx, &lunogram.OrganizationUserRequest{
	Organization: lunogram.OrganizationRef{
		Identifier: []lunogram.ExternalID{{ExternalID: "org_456"}},
	},
	User: lunogram.UserRef{
		Identifier: []lunogram.ExternalID{{ExternalID: "user_123"}},
	},
	Data: map[string]any{
		"role":       "admin",
		"department": "engineering",
	},
})

Remove a user from an organization

err := client.RemoveOrganizationUser(ctx, &lunogram.RemoveOrganizationUserRequest{
	Organization: lunogram.OrganizationRef{
		Identifier: []lunogram.ExternalID{{ExternalID: "org_456"}},
	},
	User: lunogram.UserRef{
		Identifier: []lunogram.ExternalID{{ExternalID: "user_123"}},
	},
})

Post organization events

Events are processed asynchronously and can trigger journeys for all users in the organization.

err := client.PostOrganizationEvents(ctx, []lunogram.OrganizationEvent{
	{
		Name: "subscription_upgraded",
		Identifier: []lunogram.ExternalID{
			{ExternalID: "org_456"},
		},
		Data: map[string]any{
			"plan":  "enterprise",
			"seats": 100,
		},
	},
})

Scheduled resources

Scheduled resources trigger journey entrance recalculation at a specific time or on a recurring interval.

User scheduled

// Single schedule
accepted, err := client.UpsertUserScheduled(ctx, &lunogram.UpsertUserScheduledRequest{
	Name: "trial_end",
	Identifier: []lunogram.ExternalID{
		{ExternalID: "user_123"},
	},
	ScheduledAt: &trialEnd, // time.Time
	Data: map[string]any{
		"plan":   "pro",
		"amount": 29.99,
	},
})

// Recurring schedule
accepted, err := client.UpsertUserScheduled(ctx, &lunogram.UpsertUserScheduledRequest{
	Name: "weekly_digest",
	Identifier: []lunogram.ExternalID{
		{ExternalID: "user_123"},
	},
	Interval: lunogram.String("168h"), // weekly
})

// Delete scheduled resource
err := client.DeleteUserScheduled(ctx, &lunogram.DeleteUserScheduledRequest{
	Name: "trial_end",
	Identifier: []lunogram.ExternalID{
		{ExternalID: "user_123"},
	},
})

Organization scheduled

accepted, err := client.UpsertOrganizationScheduled(ctx, &lunogram.UpsertOrganizationScheduledRequest{
	Name: "contract_renewal",
	Identifier: []lunogram.ExternalID{
		{ExternalID: "org_456"},
	},
	ScheduledAt: &renewalDate,
	Data: map[string]any{
		"contract_type": "enterprise",
		"seats":         100,
	},
})

err := client.DeleteOrganizationScheduled(ctx, &lunogram.DeleteOrganizationScheduledRequest{
	Name: "contract_renewal",
	Identifier: []lunogram.ExternalID{
		{ExternalID: "org_456"},
	},
})

Error handling

All methods return an *lunogram.APIError when the API responds with a non-2xx status code. You can inspect it for details:

user, err := client.UpsertUser(ctx, req)
if err != nil {
	var apiErr *lunogram.APIError
	if errors.As(err, &apiErr) {
		fmt.Printf("API error %d: %s — %s\n", apiErr.StatusCode, apiErr.Title, apiErr.Detail)
	}
	return err
}

External identifiers

Many requests accept one or more external identifiers. The Source field defaults to "default" when omitted.

// Simple identifier (source defaults to "default")
lunogram.ExternalID{ExternalID: "user_123"}

// Explicit source
lunogram.ExternalID{Source: "stripe", ExternalID: "cus_abc123"}

// With metadata
lunogram.ExternalID{
	Source:     "hubspot",
	ExternalID: "contact_789",
	Metadata:   map[string]any{"synced": true},
}

License

See LICENSE for details.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors