Skip to main content
The official Go SDK (github.com/playcamp/playcamp-go-sdk) provides a type-safe way to integrate with the PlayCamp API. It handles authentication, pagination, retries, and error handling with zero external dependencies.

Installation

go get github.com/playcamp/playcamp-go-sdk
Requirements: Go >= 1.21

Quick Start

import playcamp "github.com/playcamp/playcamp-go-sdk"

server, err := playcamp.NewServer("your_server_key:your_secret",
    playcamp.WithEnvironment(playcamp.EnvironmentSandbox),
)
if err != nil {
    log.Fatal(err)
}

// Create a sponsor
sponsor, err := server.Sponsors.Create(ctx, playcamp.CreateSponsorParams{
    UserID:     "user_12345",
    CreatorKey: "ABC12",
})

// Register a payment
payment, err := server.Payments.Create(ctx, playcamp.CreatePaymentParams{
    UserID:        "user_12345",
    TransactionID: "txn_abc123",
    ProductID:     "gem_pack_100",
    Amount:        9900,
    Currency:      "KRW",
    Platform:      playcamp.PaymentPlatformAndroid,
    DistributionType: playcamp.String("MOBILE_STORE"),
    PurchasedAt:   time.Now(),
})

Client vs Server

The SDK provides two constructors depending on your API key type:
ConstructorAPI KeyAccessUse Case
NewClientClient KeyRead-onlyGame client, public queries
NewServerServer KeyRead/WriteGame server, all operations
import playcamp "github.com/playcamp/playcamp-go-sdk"

// Read-only access (Client Key)
client, err := playcamp.NewClient("your_client_key:your_secret")

// Full access (Server Key)
server, err := playcamp.NewServer("your_server_key:your_secret")
Never use NewServer or expose your Server Key on the client side.

Client Resources

ResourceMethods
CampaignsList(), ListAll(), Get(), GetCreators(), GetPackages()
CreatorsGet(), Search()
CouponsValidate()
SponsorsGet()

Server Resources

ResourceMethods
CampaignsList(), ListAll(), Get(), GetCreators()
CreatorsGet(), Search(), GetCoupons()
CouponsValidate(), Redeem(), GetUserHistory(), ListAllUserHistory()
SponsorsCreate(), GetByUser(), Update(), Delete(), GetHistory(), ListAllHistory()
PaymentsCreate(), Get(), ListByUser(), ListAllByUser(), Refund()
WebhooksList(), Create(), Update(), Delete(), GetLogs(), Test()

Configuration

server, err := playcamp.NewServer("key:secret",
    playcamp.WithEnvironment(playcamp.EnvironmentSandbox), // default: EnvironmentLive
    playcamp.WithTimeout(30 * time.Second),                // default: 30s
    playcamp.WithTestMode(true),                           // default: false
    playcamp.WithMaxRetries(3),                            // default: 3
    playcamp.WithDebug(playcamp.DebugOptions{              // default: disabled
        Enabled:         true,
        LogRequestBody:  true,
        LogResponseBody: true,
    }),
)

Environments

EnvironmentURLPurpose
EnvironmentSandboxhttps://sandbox-sdk-api.playcamp.ioDevelopment/Testing
EnvironmentLivehttps://sdk-api.playcamp.ioProduction (default)
You can also specify a custom URL directly:
server, err := playcamp.NewServer("key:secret",
    playcamp.WithBaseURL("http://localhost:3003"), // Overrides environment setting
)

Pointer Helpers

Use built-in helpers for optional fields:
playcamp.String("value")   // *string
playcamp.Int(10)           // *int
playcamp.Bool(true)        // *bool
playcamp.Float64(99.99)    // *float64

Pagination

List endpoints return paginated results:
// Get a single page
result, err := server.Campaigns.List(ctx, &playcamp.PaginationOptions{
    Page:  playcamp.Int(1),
    Limit: playcamp.Int(20),
})
// result.Data, result.Pagination, result.HasNextPage
Use the iterator to automatically page through all results:
iterator := server.Campaigns.ListAll(&playcamp.PaginationOptions{
    Limit: playcamp.Int(50),
})

for iterator.Next(ctx) {
    campaign := iterator.Item()
    fmt.Println(campaign.CampaignID)
    iterator.Advance()
}

if err := iterator.Err(); err != nil {
    log.Fatal(err)
}

Error Handling

The SDK returns typed errors for different scenarios:
import "errors"

campaign, err := server.Campaigns.Get(ctx, "invalid_id")
if err != nil {
    var notFoundErr *playcamp.NotFoundError
    var authErr     *playcamp.AuthError
    var rateLimitErr *playcamp.RateLimitError
    var networkErr  *playcamp.NetworkError
    var apiErr      *playcamp.APIError

    switch {
    case errors.As(err, &notFoundErr):
        fmt.Println("Campaign not found")
    case errors.As(err, &authErr):
        fmt.Println("Invalid API key")
    case errors.As(err, &rateLimitErr):
        fmt.Println("Rate limited:", rateLimitErr.Message)
    case errors.As(err, &networkErr):
        fmt.Println("Network error:", networkErr.Message)
    case errors.As(err, &apiErr):
        fmt.Printf("API error [%d]: %s\n", apiErr.StatusCode, apiErr.Message)
    default:
        fmt.Println("Unexpected error:", err)
    }
}
Error TypeHTTP StatusDescription
BadRequestError400Malformed request
AuthError401Authentication failed
ForbiddenError403Insufficient permissions
NotFoundError404Resource not found
ConflictError409Resource conflict (duplicate)
ValidationError422Server-side validation failed
RateLimitError429Rate limit exceeded
NetworkErrorNetwork/timeout error
InputValidationErrorClient-side parameter validation

Webhook Verification

The SDK provides the webhookutil package for verifying incoming webhook signatures:
import "github.com/playcamp/playcamp-go-sdk/webhookutil"

func handleWebhook(w http.ResponseWriter, r *http.Request) {
    body, _ := io.ReadAll(r.Body)

    result := webhookutil.Verify(webhookutil.VerifyOptions{
        Payload:   body,
        Signature: r.Header.Get("X-Webhook-Signature"),
        Secret:    "your_webhook_secret",
        Tolerance: 300, // Max age in seconds (default: 300)
    })

    if !result.Valid {
        http.Error(w, result.Error, http.StatusUnauthorized)
        return
    }

    for _, event := range result.Payload.Events {
        switch event.Event {
        case playcamp.WebhookEventCouponRedeemed:
            var data playcamp.CouponRedeemedData
            json.Unmarshal(event.Data, &data)
            fmt.Printf("Coupon redeemed: %s\n", data.CouponCode)
        case playcamp.WebhookEventPaymentCreated:
            var data playcamp.PaymentCreatedData
            json.Unmarshal(event.Data, &data)
            fmt.Printf("Payment created: %s\n", data.TransactionID)
        case playcamp.WebhookEventSponsorCreated:
            var data playcamp.SponsorCreatedData
            json.Unmarshal(event.Data, &data)
            fmt.Printf("Sponsor created: %s\n", data.UserID)
        }
    }

    w.WriteHeader(http.StatusOK)
    json.NewEncoder(w).Encode(map[string]bool{"received": true})
}
For testing, you can generate signatures locally:
import "github.com/playcamp/playcamp-go-sdk/webhookutil"

payload := []byte(`{"events":[{"event":"coupon.redeemed","timestamp":"2024-01-15T10:30:00Z","data":{"couponCode":"TEST","userId":"user_123","usageId":1,"reward":[]}}]}`)

signature := webhookutil.ConstructSignature(payload, "your_webhook_secret", nil)
See the Webhook Events page for more details on webhook event types and payloads.

Example Project

For a complete working example with all API endpoints, see the playcamp-go-sdk-example repository.