Go SDK
github.com/midnight-auth/sdk-go
Installation
go get github.com/midnight-auth/sdk-go
Quick Start
package main
import (
"context"
"fmt"
"log"
ma "github.com/midnight-auth/sdk-go"
)
func main() {
client, err := ma.NewClient(ma.Config{
BaseURL: "https://auth.yourapp.com/api/v1",
APIKey: "ma_your_api_key_here", // from Console → Apps
})
if err != nil {
log.Fatal(err)
}
// Check API health
health, err := client.Health(context.Background())
if err != nil {
log.Fatal(err)
}
fmt.Println(health.Status) // "ok"
}Configuration
| Param | Type | Required | Description |
|---|---|---|---|
| BaseURL | string | Yes | Midnight Auth API base URL |
| APIKey | string | Yes | Partner app API key (ma_...) |
| Timeout | time.Duration | No | HTTP request timeout (default: 30s) |
Login Flow
Your app initiates a login session, shows a QR code, and polls until the user approves in their wallet.
client.Login.Initiate(ctx, requirements, redirectURL)
Start a new login session. Returns QR code and deep link for the wallet.
ctx := context.Background()
session, err := client.Login.Initiate(ctx, []string{"email", "phone"}, "")
if err != nil {
log.Fatal(err)
}
// session.SessionID — unique session ID
// session.QRCodeURL — data:image/png base64 QR code
// session.DeepLink — midnight-auth://login?session=...
// session.ExpiresAt — ISO timestamp (5 min TTL)
// session.AppName — your registered app name| Param | Type | Required | Description |
|---|---|---|---|
| requirements | []string | Yes | Credential types: "email", "phone", "social", "humanity", "age" |
| redirectURL | string | No | URL to redirect after login (pass "" to omit) |
client.Login.WaitForResult(ctx, sessionID, opts)
Polls session status until verified, expired, or denied. Recommended approach.
result, err := client.Login.WaitForResult(ctx, session.SessionID,
&ma.WaitForResultOptions{
Timeout: 120 * time.Second,
Interval: 2 * time.Second,
OnStatusChange: func(status string) {
fmt.Println("Status:", status) // "pending" → "verified"
},
},
)
if err != nil {
log.Fatal(err)
}
if result.Verified {
fmt.Println(result.UserID) // "usr_7x8m2k..."
fmt.Println(result.EmailDomain) // "gmail.com"
}client.Login.GetStatus(ctx, sessionID)
Manual status check (use if you prefer custom polling).
status, err := client.Login.GetStatus(ctx, session.SessionID) // status.Status: "pending" | "verified" | "expired" | "denied"
client.Login.GetResult(ctx, sessionID)
Fetch verified result data. Only returns data when status is "verified".
result, err := client.Login.GetResult(ctx, session.SessionID)
Login Result Struct
The result struct only contains booleans and derived metadata — never raw PII. Fields are populated only if the matching credential was required and verified.
type LoginResultResponse struct {
Verified bool // true if login succeeded
UserID string // app-specific pseudonymous ID ("usr_7a8b3c...")
VerifiedAt string // ISO timestamp
// Email credential
EmailVerified bool
EmailDomain string // domain only, not the address
DomainType string // "consumer" | "business" | "edu"
// Phone credential
PhoneVerified bool
PhoneCountry string // country code only
CarrierType string // "mobile" | "voip" | "landline"
// Social credential
HasSocial bool
SocialPlatform string
AccountAgeMonths int
FollowerRange string // "1k-10k"
// Humanity credential
IsHuman bool
HumanityScore float64
// Age credential
Over18 bool
Over21 bool
Over25 bool
}Onboarding Flow
Issue verifiable credentials to users' wallets. Each step issues an ACDC credential. All methods accept a context.Context for cancellation.
ctx := context.Background() // Step 1: Connect wallet session, _ := client.Onboard.ConnectWallet(ctx, "D_user_keri_aid_here") // Step 2: Email verification _, _ = client.Onboard.SendEmailCode(ctx, session.SessionID, "user@example.com") _, _ = client.Onboard.VerifyEmailCode(ctx, session.SessionID, "123456") // Step 3: Phone verification _, _ = client.Onboard.SendPhoneCode(ctx, session.SessionID, "+1234567890") _, _ = client.Onboard.VerifyPhoneCode(ctx, session.SessionID, "654321") // Step 4: Social auth social, _ := client.Onboard.StartSocialAuth(ctx, "twitter", session.SessionID) // Redirect user to social.AuthorizationURL // Step 5: Humanity check _, _ = client.Onboard.VerifyHumanity(ctx, session.SessionID, "hcaptcha_token") // Check progress status, _ := client.Onboard.GetSessionStatus(ctx, session.SessionID) fmt.Println(status.CompletedSteps) // ["email", "phone"]
Error Handling
import "errors"
session, err := client.Login.Initiate(ctx, []string{"email"}, "")
if err != nil {
var apiErr *ma.Error
if errors.As(err, &apiErr) {
fmt.Println(apiErr.StatusCode) // 403
fmt.Println(apiErr.Message) // "Invalid or inactive API key"
}
}Context & Cancellation
All methods accept context.Context for deadline and cancellation support.
// Cancel after 5 seconds
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
health, err := client.Health(ctx)
if err != nil {
// err will be context.DeadlineExceeded if it times out
log.Fatal(err)
}