tangerino

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 11, 2026 License: MIT Imports: 11 Imported by: 0

README

Unofficial Tangerino Employer API

Go Reference Go Version Go Report Card License

A Go client library for the Tangerino Employer API.

Covers the core employer modules: Employees, Companies, Holiday Calendars, Work Schedules, Workplaces, and Punches.


Installation

go get github.com/raykavin/tangerino-go

Requires Go 1.22+. No external dependencies — uses only the Go standard library.


Quick Start

import tangerino "github.com/raykavin/tangerino-go"

client, err := tangerino.NewClient("your-username", "your-password")
if err != nil {
    log.Fatal(err)
}

ctx := context.Background()

// List employees (first page)
page, err := client.Employees.List(ctx, tangerino.ListEmployeesParams{Size: 20})
if err != nil {
    log.Fatal(err)
}

for _, e := range page.Content {
    fmt.Println(e.ID, e.Name, e.AdmissionDate.Format("02/01/2006"))
}

Configuration

// Production environment (default)
client, err := tangerino.NewClient("username", "password")

// Custom base URL (e.g. for testing)
opt, err := tangerino.WithBaseURL("https://custom.tangerino.example.com")
if err != nil {
    log.Fatal(err)
}
client, err = tangerino.NewClient("username", "password", opt)

// Staging environment
client, err = tangerino.NewClient("username", "password", tangerino.WithStagingEnv())

// Custom HTTP client (for TLS, proxies, custom timeouts, etc.)
httpClient := &http.Client{Timeout: 60 * time.Second}
client, err = tangerino.NewClient("username", "password", tangerino.WithHTTPClient(httpClient))

Authentication

The Tangerino API uses HTTP Basic Authentication. Credentials are encoded and sent automatically on every request — no additional setup is required after creating the client.

client, err := tangerino.NewClient("your-username", "your-password")

Modules

Employees
// List employees (paginated)
page, err := client.Employees.List(ctx, tangerino.ListEmployeesParams{
    Size: 20,
})
fmt.Printf("Page 1 of %d (%d total)\n", page.TotalPages, page.TotalElements)

// Apply filters
page, err = client.Employees.List(ctx, tangerino.ListEmployeesParams{
    Size:              20,
    BranchExternalID:  "branch-001",
    ManagerExternalID: "manager-042",
    ShowFired:         1, // include terminated employees
})

// Filter by last update (Unix timestamp in milliseconds)
page, err = client.Employees.List(ctx, tangerino.ListEmployeesParams{
    LastUpdate: time.Now().Add(-24 * time.Hour).UnixMilli(),
    Size:       50,
})

// Iterate all pages
params := tangerino.ListEmployeesParams{Size: 50}
for {
    page, err := client.Employees.List(ctx, params)
    if err != nil {
        log.Fatal(err)
    }
    for _, e := range page.Content {
        fmt.Println(e.ID, e.Name)
    }
    if !page.HasNext() {
        break
    }
    params.Page = page.NextPageNumber()
}

// Access typed date fields
for _, e := range page.Content {
    fmt.Println(e.AdmissionDate.Format("02/01/2006")) // "01/04/2025"
    fmt.Println(e.AdmissionDate.Raw())                // 1743462000000
    fmt.Println(e.AdmissionDate.Time())               // time.Time

    if e.BirthDate != nil {
        fmt.Println(e.BirthDate.Format("02/01/2006"))
    }
}

Companies
// List companies (paginated)
page, err := client.Companies.List(ctx, tangerino.ListCompaniesParams{
    Size: 20,
})

// Explicit page navigation
page, err = client.Companies.List(ctx, tangerino.ListCompaniesParams{
    Page: 1,
    Size: 10,
})

for _, c := range page.Content {
    fmt.Println(c.ID, c.CNPJ, c.SocialReason, c.FantasyName)
}

Holiday Calendars
// List all holiday calendars for the employer
calendars, err := client.HolidayCalendars.List(ctx)
if err != nil {
    log.Fatal(err)
}

for _, cal := range calendars {
    fmt.Printf("[%d] %s (%d)\n", cal.ID, cal.Name, cal.Year)
    for _, h := range cal.Holidays {
        fmt.Printf("  %s - %s\n", h.Date, h.Description)
    }
}

Work Schedules
// List all work schedules
page, err := client.WorkSchedules.List(ctx, tangerino.ListWorkSchedulesParams{
    Size: 50,
})
if err != nil {
    log.Fatal(err)
}

for _, ws := range page.Content {
    fmt.Printf("[%d] %s (standard: %v, inactive: %v)\n",
        ws.ID, ws.Name, ws.Standard, ws.Inactive)

    for _, tt := range ws.Timetable {
        fmt.Printf("  Day %d: %s - %s",
            tt.Day,
            tt.StartShift1.String(), // "08:00"
            tt.EndShift1,            // *DayOffset, check nil before use
        )
        if tt.StartShift2 != nil {
            fmt.Printf(" | %s - %s",
                tt.StartShift2.String(),
                tt.EndShift2,
            )
        }
        fmt.Println()
    }

    fmt.Println("Last modified:", ws.AlterationDate.Format("02/01/2006"))
}

Workplaces
// List workplaces (paginated)
page, err := client.Workplaces.List(ctx, tangerino.ListWorkplacesParams{
    Size: 20,
})
if err != nil {
    log.Fatal(err)
}

for _, w := range page.Content {
    fmt.Printf("[%d] %s — %s, %s\n", w.ID, w.Name, w.City, w.State)
}

// Iterate all pages
params := tangerino.ListWorkplacesParams{Size: 50}
for {
    page, err := client.Workplaces.List(ctx, params)
    if err != nil {
        log.Fatal(err)
    }
    for _, w := range page.Content {
        fmt.Println(w.ID, w.Name)
    }
    if !page.HasNext() {
        break
    }
    params.Page = page.NextPageNumber()
}

Punches

The punch endpoints live on a separate host (apis.tangerino.com.br) — the client handles routing automatically.

adj := true
pending := false

// List punch records for an employee
punches, err := client.Punches.List(ctx, employeeID, tangerino.PunchesParams{
    Status:     3,
    Adjustment: &adj,
    StartDate:  time.Now().AddDate(0, -1, 0), // converted to Unix seconds
    EndDate:    time.Now(),
    Pending:    &pending,
})
if err != nil {
    log.Fatal(err)
}

for _, p := range punches {
    end := "open"
    if p.EndDate != nil {
        end = p.EndDate.String() // "2026-06-01T18:02:00"
    }
    fmt.Printf("[%d] %s  %s → %s  (%s manual: start=%v end=%v)\n",
        p.ID, p.Date,
        p.StartDate.String(), end,
        formatMillis(p.TotalHours),
        p.StartManual, p.EndManual,
    )
}

// Get aggregate summary for an employee
summary, err := client.Punches.Summary(ctx, employeeID, tangerino.PunchesParams{
    StartDate: time.Now().AddDate(0, -1, 0),
    EndDate:   time.Now(),
})
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Worked: %dms  Expected: %dms  Balance: %dms\n",
    summary.TotalWorked, summary.TotalExpected, summary.Balance)

StartDate and EndDate are time.Time values and are automatically converted to Unix second timestamps in the request query string.

Adjustment and Pending are *bool — use a pointer so that false is distinguishable from "not set":

t, f := true, false
tangerino.PunchesParams{Adjustment: &t, Pending: &f}

Custom Types

UnixMilliTime

Used for absolute timestamps (AdmissionDate, BirthDate, EffectiveDate, AlterationDate, StartDate). Preserves the original Unix millisecond value and provides conversion helpers.

ts := employee.AdmissionDate

ts.Raw()                     // int64   → 1776049200000  (original API value)
ts.Time()                    // time.Time (UTC)
ts.Format("02/01/2006")      // string  → "01/04/2026"
ts.Format("15:04")           // string  → "03:00" (UTC hour)
ts.Format(time.RFC3339)      // string  → "2026-04-01T03:00:00Z"
ts.String()                  // string  → "2026-04-01 03:00:00 UTC"
DayOffset

Used for time-of-day offsets in work schedule timetables (StartShift1, EndShift1, StartShift2, EndShift2, StartMainInterval, EndMainInterval). Values are milliseconds from midnight and may exceed 86400000 (24 h) for shifts that extend into the next day.

d := timetable.StartShift1

d.Raw()       // int64         → 39600000    (original API value)
d.Duration()  // time.Duration → 11h0m0s
d.String()    // string        → "11:00"

// Shifts past midnight (e.g. 12x36 schedule):
// EndShift2 = 100800000 → "28:00"
LocalDateTime

Used for punch timestamps (StartDate, EndDate in Punch). Represents a wall-clock datetime without timezone in the format "2006-01-02T15:04:05".

p := punches[0]

p.StartDate.String()  // "2026-06-01T14:06:00"
p.StartDate.Time()    // time.Time (no timezone — server local time)

// EndDate is *LocalDateTime, nil when the employee hasn't clocked out yet
if p.EndDate != nil {
    fmt.Println(p.EndDate.String())
}

Pagination

Paginated endpoints return *Page[T], a generic type wrapping the Spring-style content envelope.

type Page[T any] struct {
    Content          []T
    First            bool
    Last             bool
    TotalElements    int
    TotalPages       int
    NumberOfElements int
    Size             int
    Number           int
}

Helper methods:

page.HasNext()         // bool: whether a next page exists
page.NextPageNumber()  // int: page number to use in the next request (-1 on last page)

Pagination parameters follow a consistent naming convention across all services:

Field Query param Description
Page page Zero-based page index
Size size Number of items per page

Full iteration pattern:

params := tangerino.ListEmployeesParams{Size: 50}
for {
    page, err := client.Employees.List(ctx, params)
    if err != nil {
        log.Fatal(err)
    }
    // process page.Content ...
    if !page.HasNext() {
        break
    }
    params.Page = page.NextPageNumber()
}

Error Handling

All methods return *APIError on HTTP-level failures.

page, err := client.Employees.List(ctx, tangerino.ListEmployeesParams{})
if err != nil {
    switch {
    case tangerino.IsUnauthorized(err):
        // HTTP 401 — invalid credentials
    case tangerino.IsForbidden(err):
        // HTTP 403 — insufficient permissions
    case tangerino.IsNotFound(err):
        // HTTP 404 — resource not found
    case tangerino.IsRateLimited(err):
        // HTTP 429 — too many requests, back off and retry
    case tangerino.IsServerError(err):
        // HTTP 5xx — transient server error
    default:
        if apiErr, ok := err.(*tangerino.APIError); ok {
            fmt.Printf("Status: %d\n", apiErr.StatusCode)
            fmt.Printf("Body:   %s\n", apiErr.Body)
        }
    }
}

Running Tests

go test ./... -v

All tests use net/http/httptest — no external services or environment variables are required.


Endpoints Coverage

Employees
  • GET /employee/find-all — List employees (paginated, with filters)
Companies
  • GET /companies — List companies (paginated)
Holiday Calendars
  • GET /holiday-calendar/ — List holiday calendars
Work Schedules
  • GET /work-schedule — List work schedules (paginated)
Workplaces
  • GET /workplace/find-all — List workplaces (paginated)
Punches
  • GET /punch/v2/punches/employees/{id} — List punch records for an employee
  • GET /punch/v2/punches/employees/{id}/summary — Get aggregate time summary for an employee

Total: 7 endpoints covered


Contributing

Contributions to tangerino-go are welcome! Here are some ways you can help:

  • Report bugs and suggest features by opening issues on GitHub
  • Submit pull requests with bug fixes or new features
  • Improve documentation to help other users and developers

License

tangerino-go is distributed under the MIT License.
For complete license terms and conditions, see the LICENSE file in the repository.


Contact

For support, collaboration, or questions about tangerino-go:

Email: raykavin.meireles@gmail.com
GitHub: @raykavin

Documentation

Overview

Package tangerino provides a client library for the Tangerino employer API.

Create a client with NewClient, then use its service fields to access API resources:

client, err := tangerino.NewClient("username", "password")
if err != nil {
    log.Fatal(err)
}

page, err := client.Employees.List(ctx, tangerino.ListEmployeesParams{Size: 20})
punches, err := client.Punches.GetEmployeePunches(ctx, employeeID)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsForbidden

func IsForbidden(err error) bool

IsForbidden reports whether err is a 403 Forbidden API error.

func IsNotFound

func IsNotFound(err error) bool

IsNotFound reports whether err is a 404 Not Found API error.

func IsRateLimited

func IsRateLimited(err error) bool

IsRateLimited reports whether err is a 429 Too Many Requests API error.

func IsServerError

func IsServerError(err error) bool

IsServerError reports whether err is a 5xx server-side API error.

func IsUnauthorized

func IsUnauthorized(err error) bool

IsUnauthorized reports whether err is a 401 Unauthorized API error.

Types

type APIError

type APIError struct {
	// StatusCode is the HTTP status code from the response.
	StatusCode int
	// Body contains the raw response body, available for debugging or custom parsing.
	Body []byte
}

APIError represents an HTTP error returned by the Tangerino API.

func (*APIError) Error

func (e *APIError) Error() string

Error implements the error interface.

type Client

type Client struct {

	// Employees provides access to employee management endpoints.
	Employees *EmployeesService
	// HolidayCalendars provides access to holiday calendar endpoints.
	HolidayCalendars *HolidayCalendarsService
	// WorkSchedules provides access to work schedule endpoints.
	WorkSchedules *WorkSchedulesService
	// Companies provides access to company endpoints.
	Companies *CompaniesService
	// Workplaces provides access to workplace endpoints.
	Workplaces *WorkplacesService
	// Punches provides access to punch clock endpoints.
	Punches *PunchesService
	// contains filtered or unexported fields
}

Client is the Tangerino API client. Use its service fields to call specific API resources.

func NewClient

func NewClient(username, password string, opts ...Option) (*Client, error)

NewClient creates an authenticated Tangerino API client. Both username and password are required for Basic Authentication and are used on every outgoing request.

type CompaniesService

type CompaniesService struct {
	// contains filtered or unexported fields
}

CompaniesService handles communication with the company endpoints.

func (*CompaniesService) List

List retrieves a single page of companies matching the given parameters. All parameters are optional; omit them by using a zero-value ListCompaniesParams.

GET /companies

type Company

type Company struct {
	// ID is the unique identifier of the company.
	ID int `json:"id"`
	// CNPJ is the company's Brazilian federal tax registration number, formatted with punctuation.
	CNPJ string `json:"cnpj"`
	// ExternalID is an optional identifier assigned by an external system.
	ExternalID string `json:"externalId"`
	// SocialReason is the company's registered legal name.
	SocialReason string `json:"socialReason"`
	// FantasyName is the company's trade name used in day-to-day operations.
	FantasyName string `json:"fantasyName"`
	// DescriptionName is the display name used in the Tangerino interface.
	DescriptionName string `json:"descriptionName"`
}

Company represents a single company record returned by the API.

type DayOffset

type DayOffset int64

DayOffset is a time offset from midnight stored as milliseconds, as received from the API. It is used for shift and interval fields in work schedule timetables. Values may exceed 86400000 (24 h) when a shift extends past midnight into the next day.

func (DayOffset) Duration

func (d DayOffset) Duration() time.Duration

Duration converts the value to a time.Duration.

func (DayOffset) Raw

func (d DayOffset) Raw() int64

Raw returns the original millisecond value as received from the API.

func (DayOffset) String

func (d DayOffset) String() string

String formats the offset as "HH:MM". Hours are not capped at 23, so a shift ending at 28 h is shown as "28:00".

type Employee

type Employee struct {
	// ID is the unique identifier of the employee.
	ID int `json:"id"`
	// Name is the employee's full legal name.
	Name string `json:"name"`
	// SocialName is the employee's preferred or social name, if provided.
	SocialName string `json:"socialName"`
	// Email is the employee's contact email address.
	Email string `json:"email"`
	// CPF is the employee's Brazilian tax identification number.
	CPF string `json:"cpf"`
	// PIS is the employee's Social Integration Program number, if provided.
	PIS string `json:"pis"`
	// Gender is the employee's gender as reported by the API (e.g. "MASCULINO", "FEMININO").
	Gender string `json:"gender"`
	// BirthDate is the employee's date of birth as a Unix millisecond timestamp.
	// It is nil when the value is not present in the API response.
	BirthDate *UnixMilliTime `json:"birthDate"`
	// AdmissionDate is the employee's hiring date as a Unix millisecond timestamp.
	AdmissionDate UnixMilliTime `json:"admissionDate"`
	// EffectiveDate is the date the current record became effective, as a Unix millisecond timestamp.
	EffectiveDate UnixMilliTime `json:"effectiveDate"`
	// ExternalID is an optional identifier assigned by an external system.
	ExternalID string `json:"externalId"`
	// CurrentWorkSchedule is a reference to the work schedule currently active for the employee.
	CurrentWorkSchedule WorkScheduleRef `json:"currentWorkSchedule"`
	// Company is a reference to the company the employee belongs to.
	Company EntityRef `json:"company"`
	// JobRole is a reference to the employee's current job role.
	JobRole EntityRef `json:"jobRoleDTO"`
	// LastManager is a reference to the employee's most recent manager.
	LastManager EntityRef `json:"lastManager"`
	// Managers holds references to all current managers for the employee.
	Managers []EntityRef `json:"managers"`
	// WorkplaceList holds references to all workplaces assigned to the employee.
	WorkplaceList []EntityRef `json:"workplaceList"`
	// Fired indicates whether the employee has been terminated.
	Fired bool `json:"fired"`
	// CanViewWorkgroup indicates whether the employee has workgroup visibility permissions.
	CanViewWorkgroup bool `json:"canViewWorkgroup"`
	// Status is the numeric status code for the employee record.
	Status int `json:"status"`
	// DoubleBindEmployee indicates whether the employee is shared across multiple companies.
	DoubleBindEmployee bool `json:"doubleBindEmployee"`
	// RecordsPunch indicates whether the employee uses the punch clock system.
	RecordsPunch bool `json:"recordsPunch"`
}

Employee represents a single employee record returned by the API.

type EmployeesService

type EmployeesService struct {
	// contains filtered or unexported fields
}

EmployeesService handles communication with the employee endpoints.

func (*EmployeesService) List

List retrieves a single page of employees matching the given parameters. All parameters are optional; omit them by using a zero-value ListEmployeesParams.

GET /employee/find-all

type EntityRef

type EntityRef struct {
	// ID is the unique identifier of the referenced entity.
	ID int `json:"id"`
}

EntityRef is a lightweight reference to a related entity identified by its ID. It is used for nested objects where the API returns only the identifier.

type Environment

type Environment struct {
	// contains filtered or unexported fields
}

Environment holds the API base URLs for a deployment target. Most resources live under employerBaseURL; punch clock endpoints use punchesBaseURL.

type Holiday

type Holiday struct {
	// ID is the unique identifier of the holiday.
	ID int `json:"id"`
	// Description is the name or label of the holiday.
	Description string `json:"description"`
	// Date is the calendar date of the holiday in YYYY-MM-DD format.
	Date string `json:"date"`
}

Holiday represents a single public or regional holiday entry within a calendar.

type HolidayCalendar

type HolidayCalendar struct {
	// ID is the unique identifier of the calendar.
	ID int `json:"id"`
	// Name is the human-readable label assigned to the calendar.
	Name string `json:"name"`
	// Description is an optional extended description of the calendar.
	Description string `json:"description"`
	// Year is the year this calendar applies to.
	Year int `json:"year"`
	// Holidays lists the individual holiday entries contained in this calendar.
	Holidays []Holiday `json:"holidays"`
}

HolidayCalendar represents a named collection of holidays for a specific year. Each calendar may cover a national, regional, or custom set of holidays.

type HolidayCalendarsService

type HolidayCalendarsService struct {
	// contains filtered or unexported fields
}

HolidayCalendarsService handles communication with the holiday calendar endpoints.

func (*HolidayCalendarsService) List

List retrieves all holiday calendars available for the authenticated employer.

GET /holiday-calendar/

type ListCompaniesParams

type ListCompaniesParams struct {
	// Page is the zero-based page index to retrieve.
	Page int
	// Size is the number of items per page.
	Size int
	// Offset is the item offset within the result set.
	Offset int
}

ListCompaniesParams holds optional filter and pagination parameters for the companies endpoint. All fields are optional; zero values are omitted from the request.

type ListEmployeesParams

type ListEmployeesParams struct {
	// BranchExternalID filters employees by the external identifier of their branch.
	BranchExternalID string
	// ManagerExternalID filters employees by the external identifier of their manager.
	ManagerExternalID string
	// LastUpdate filters employees modified after this Unix timestamp in milliseconds.
	LastUpdate int64
	// Page is the zero-based page index to retrieve.
	Page int
	// Size is the number of items per page.
	Size int
	// Offset is the item offset within the result set.
	Offset int
	// ShowFired controls whether terminated employees are included (0 = exclude, 1 = include).
	ShowFired int
}

ListEmployeesParams holds optional filter and pagination parameters for the employee list endpoint. All fields are optional; zero values are omitted from the request.

type ListWorkSchedulesParams added in v0.1.0

type ListWorkSchedulesParams struct {
	// Page is the zero-based page index to retrieve.
	Page int
	// Size is the number of items per page.
	Size int
}

ListWorkSchedulesParams holds optional pagination parameters for the work schedule endpoint. All fields are optional; zero values are omitted from the request.

type ListWorkplacesParams added in v0.1.0

type ListWorkplacesParams struct {
	// Page is the zero-based page index to retrieve.
	Page int
	// Size is the number of items per page.
	Size int
}

ListWorkplacesParams holds optional pagination parameters for the workplace list endpoint. All fields are optional; zero values are omitted from the request.

type LocalDateTime added in v0.1.0

type LocalDateTime struct {
	// contains filtered or unexported fields
}

LocalDateTime is a wall-clock datetime without timezone, stored in the format "2006-01-02T15:04:05" as returned by the punch API. Use Time() to obtain a time.Time (interpreted in the local timezone of the server).

func (LocalDateTime) MarshalJSON added in v0.1.0

func (d LocalDateTime) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (LocalDateTime) String added in v0.1.0

func (d LocalDateTime) String() string

String returns the value formatted as "2006-01-02T15:04:05".

func (LocalDateTime) Time added in v0.1.0

func (d LocalDateTime) Time() time.Time

Time returns the underlying time.Time value.

func (*LocalDateTime) UnmarshalJSON added in v0.1.0

func (d *LocalDateTime) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler.

type Option

type Option func(*Client)

Option is a functional option for configuring a Client.

func WithHTTPClient

func WithHTTPClient(hc *http.Client) Option

WithHTTPClient replaces the default HTTP client with a custom one. Use this to configure custom timeouts, TLS settings, or proxies.

func WithStagingEnv

func WithStagingEnv() Option

WithStagingEnv points the client at the staging environment.

type Page

type Page[T any] struct {
	// Content holds the items on the current page.
	Content []T `json:"content"`
	// First indicates whether this is the first page.
	First bool `json:"first"`
	// Last indicates whether this is the last page.
	Last bool `json:"last"`
	// TotalElements is the total number of items across all pages.
	TotalElements int `json:"totalElements"`
	// TotalPages is the total number of pages available.
	TotalPages int `json:"totalPages"`
	// NumberOfElements is the number of items on this page.
	NumberOfElements int `json:"numberOfElements"`
	// Size is the maximum number of items per page as requested.
	Size int `json:"size"`
	// Number is the zero-based index of the current page.
	Number int `json:"number"`
}

Page is a generic paginated response from the Tangerino API. It wraps a slice of T alongside Spring-style pagination metadata. Any endpoint that returns a paginated collection uses this type as its response.

Example:

page, err := client.Employees.List(ctx, tangerino.ListEmployeesParams{Size: 20})
for !page.IsLast() {
    // process page.Content ...
    params.Page++
    page, err = client.Employees.List(ctx, params)
}

func (*Page[T]) HasNext

func (p *Page[T]) HasNext() bool

HasNext reports whether there is at least one more page after this one.

func (*Page[T]) NextPageNumber

func (p *Page[T]) NextPageNumber() int

NextPageNumber returns the number to pass as Page in the next request. Returns -1 when the current page is the last one.

type Punch added in v0.1.0

type Punch struct {
	// ID is the unique identifier of the punch record.
	ID int `json:"id"`
	// Date is the calendar date of the punch in "YYYY-MM-DD" format.
	Date string `json:"date"`
	// StartDate is the clock-in time for this interval.
	StartDate LocalDateTime `json:"startDate"`
	// EndDate is the clock-out time for this interval.
	// It is nil when the employee has not yet clocked out.
	EndDate *LocalDateTime `json:"endDate"`
	// Status is the numeric status code of the punch record (e.g. 2 = approved).
	Status int `json:"status"`
	// StartManual indicates whether the clock-in was entered manually.
	StartManual bool `json:"startManual"`
	// EndManual indicates whether the clock-out was entered manually.
	EndManual bool `json:"endManual"`
	// Pending indicates whether the punch is awaiting approval.
	Pending bool `json:"pending"`
	// Accredited indicates whether the punch has been credited to the hours bank.
	Accredited bool `json:"accredited"`
	// Adjustment indicates whether this punch record was adjusted.
	Adjustment bool `json:"adjustment"`
	// Canceled indicates whether the punch has been voided.
	Canceled bool `json:"canceled"`
	// TotalHours is the duration of the interval in milliseconds.
	// Despite the name, the API returns a millisecond value (e.g. 14400000 = 4 h).
	TotalHours int64 `json:"totalHours"`
}

Punch represents a single work interval record (a pair of clock-in / clock-out events). Each punch covers one continuous work block; a day with a lunch break typically has two.

type PunchSummary added in v0.1.0

type PunchSummary struct {
	// EmployeeID is the identifier of the employee.
	EmployeeID int `json:"employeeId"`
	// TotalWorked is the total time worked in milliseconds.
	TotalWorked int64 `json:"totalWorked"`
	// TotalExpected is the expected work time in milliseconds.
	TotalExpected int64 `json:"totalExpected"`
	// Balance is the difference between worked and expected time in milliseconds.
	// Positive values indicate overtime; negative values indicate a deficit.
	Balance int64 `json:"balance"`
	// Absences is the number of absence days in the period.
	Absences int `json:"absences"`
	// Delays is the total delay time in milliseconds.
	Delays int64 `json:"delays"`
	// Overtime is the total overtime in milliseconds.
	Overtime int64 `json:"overtime"`
	// HoursBank is the accumulated hours-bank balance in milliseconds.
	HoursBank int64 `json:"hoursBank"`
}

PunchSummary holds aggregate time data for an employee over a queried period.

type PunchesParams added in v0.1.0

type PunchesParams struct {
	// Status filters punches by status code (e.g. 3 for pending approval).
	Status int
	// Adjustment filters by whether the punch was manually adjusted.
	// Pass a pointer to true or false; nil omits the parameter.
	Adjustment *bool
	// StartDate is the inclusive start of the date range.
	// Converted to a Unix second timestamp when building the request.
	StartDate time.Time
	// EndDate is the inclusive end of the date range.
	// Converted to a Unix second timestamp when building the request.
	EndDate time.Time
	// Pending filters by whether the punch is awaiting approval.
	// Pass a pointer to true or false; nil omits the parameter.
	Pending *bool
}

PunchesParams holds filter parameters for punch clock endpoints. StartDate and EndDate accept time.Time values and are sent to the API as Unix second timestamps. Zero-value time.Time fields are omitted. Adjustment and Pending are pointer booleans so that false can be distinguished from "not set".

type PunchesService added in v0.1.0

type PunchesService struct {
	// contains filtered or unexported fields
}

PunchesService handles communication with the punch clock endpoints.

func (*PunchesService) List added in v0.1.0

func (s *PunchesService) List(ctx context.Context, employeeID int, params PunchesParams) ([]Punch, error)

List retrieves all punch records for the given employee matching the filter params.

GET /punch/v2/punches/employees/{employeeID}

type UnixMilliTime

type UnixMilliTime int64

UnixMilliTime is an absolute timestamp stored as milliseconds since the Unix epoch, exactly as received from the API. It provides helpers to access the raw value or convert to standard Go types without losing precision.

func (UnixMilliTime) Format

func (t UnixMilliTime) Format(layout string) string

Format formats the timestamp using the given layout (same syntax as time.Time.Format).

Example:

t.Format("02/01/2006")       // "01/01/2025"
t.Format("15:04")            // "09:00"
t.Format(time.RFC3339)

func (UnixMilliTime) Raw

func (t UnixMilliTime) Raw() int64

Raw returns the original Unix millisecond value as received from the API.

func (UnixMilliTime) String

func (t UnixMilliTime) String() string

String returns the timestamp formatted as "2006-01-02 15:04:05 UTC".

func (UnixMilliTime) Time

func (t UnixMilliTime) Time() time.Time

Time converts the value to a time.Time in UTC.

type WorkSchedule

type WorkSchedule struct {
	// ID is the unique identifier of the work schedule.
	ID int `json:"id"`
	// Name is the human-readable label for the work schedule.
	Name string `json:"name"`
	// Standard indicates whether this is the default system schedule.
	Standard bool `json:"standard"`
	// Timetable holds the per-day time configurations for this schedule.
	Timetable []WorkScheduleTimetable `json:"workScheduleTimetableList"`
	// AlterationDate is the Unix millisecond timestamp of the last modification.
	AlterationDate UnixMilliTime `json:"alterationDate"`
	// PreAssignedInterval indicates whether break intervals are pre-assigned across the schedule.
	PreAssignedInterval bool `json:"preAssignedInterval"`
	// ShowIntradayInTimeSheet indicates whether intraday entries appear in the time sheet.
	ShowIntradayInTimeSheet bool `json:"showIntradayInTimeSheet"`
	// IgnoreHoliday indicates whether this schedule applies on public holidays.
	IgnoreHoliday bool `json:"ignoreHoliday"`
	// Inactive indicates whether the schedule has been deactivated.
	Inactive bool `json:"inactive"`
}

WorkSchedule represents a full work schedule definition including its daily timetables.

type WorkScheduleRef

type WorkScheduleRef struct {
	// ID is the unique identifier of the work schedule.
	ID int `json:"id"`
	// StartDate is the Unix timestamp (milliseconds) when the schedule became effective for the employee.
	StartDate UnixMilliTime `json:"startDate"`
	// Inactive indicates whether the schedule has been deactivated.
	Inactive bool `json:"inactive"`
}

WorkScheduleRef is a lightweight reference to a work schedule as embedded in an employee record. For the full work schedule details use WorkSchedule, returned by WorkSchedulesService.

type WorkScheduleTimetable

type WorkScheduleTimetable struct {
	// ID is the unique identifier of this timetable entry.
	ID int `json:"id"`
	// Day is the day of the week this entry applies to (1=Sunday, 2=Monday, ..., 7=Saturday).
	Day int `json:"day"`
	// StartMainInterval is the start of the main break period as a day offset.
	StartMainInterval DayOffset `json:"startMainInterval"`
	// EndMainInterval is the end of the main break period as a day offset.
	// It is nil when the schedule has no defined end for the main interval.
	EndMainInterval *DayOffset `json:"endMainInterval"`
	// StartShift1 is the start of the first shift as a day offset.
	StartShift1 DayOffset `json:"startShift1"`
	// EndShift1 is the end of the first shift as a day offset.
	// It is nil when the first shift has no defined end time.
	EndShift1 *DayOffset `json:"endShift1"`
	// StartShift2 is the start of the second shift as a day offset.
	// It is nil when there is no second shift.
	StartShift2 *DayOffset `json:"startShift2"`
	// EndShift2 is the end of the second shift as a day offset.
	// It is nil when there is no second shift.
	EndShift2 *DayOffset `json:"endShift2"`
	// IntervalPreAssigned1And2 indicates whether the interval between shifts 1 and 2 is pre-assigned.
	IntervalPreAssigned1And2 bool `json:"intervalPreAssigned1And2"`
	// IntervalPreAssigned2And3 indicates whether the interval between shifts 2 and 3 is pre-assigned.
	IntervalPreAssigned2And3 bool `json:"intervalPreAssigned2And3"`
	// IntervalPreAssigned3And4 indicates whether the interval between shifts 3 and 4 is pre-assigned.
	IntervalPreAssigned3And4 bool `json:"intervalPreAssigned3And4"`
	// IntervalPreAssigned4And5 indicates whether the interval between shifts 4 and 5 is pre-assigned.
	IntervalPreAssigned4And5 bool `json:"intervalPreAssigned4And5"`
	// IntervalPreAssigned5And6 indicates whether the interval between shifts 5 and 6 is pre-assigned.
	IntervalPreAssigned5And6 bool `json:"intervalPreAssigned5And6"`
}

WorkScheduleTimetable represents the time configuration for a single day within a work schedule. All interval values are milliseconds elapsed since midnight.

type WorkSchedulesService

type WorkSchedulesService struct {
	// contains filtered or unexported fields
}

WorkSchedulesService handles communication with the work schedule endpoints.

func (*WorkSchedulesService) List

List retrieves a single page of work schedules available for the authenticated employer. All parameters are optional; omit them by using a zero-value ListWorkSchedulesParams.

GET /work-schedule

type Workplace added in v0.1.0

type Workplace struct {
	// ID is the unique identifier of the workplace.
	ID int `json:"id"`
	// Name is the human-readable label for the workplace.
	Name string `json:"name"`
	// ExternalID is an optional identifier assigned by an external system.
	ExternalID string `json:"externalId"`
	// Company is a reference to the company this workplace belongs to.
	Company EntityRef `json:"company"`
	// Address is the street address of the workplace.
	Address string `json:"address"`
	// City is the city where the workplace is located.
	City string `json:"city"`
	// State is the state or province where the workplace is located.
	State string `json:"state"`
	// ZipCode is the postal code of the workplace.
	ZipCode string `json:"zipCode"`
	// Inactive indicates whether the workplace has been deactivated.
	Inactive bool `json:"inactive"`
}

Workplace represents a single workplace record returned by the API.

type WorkplacesService added in v0.1.0

type WorkplacesService struct {
	// contains filtered or unexported fields
}

WorkplacesService handles communication with the workplace endpoints.

func (*WorkplacesService) List added in v0.1.0

List retrieves a single page of workplaces for the authenticated employer. All parameters are optional; omit them by using a zero-value ListWorkplacesParams.

GET /workplace/find-all

Directories

Path Synopsis
internal
retry
Package retry provides exponential backoff utilities for HTTP retries.
Package retry provides exponential backoff utilities for HTTP retries.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL