# Go Client Library

## Installation

```bash
go get github.com/tomba-io/go/tomba
```

## Usage

### Domain Search

Get email addresses found on the internet.

```go
package main

import (
	"fmt"

	"github.com/tomba-io/go/tomba"
)

func main() {
	client := tomba.New("ta_xxxxx", "ts_xxxxx")

	result, err := client.DomainSearch(tomba.Params{
		"domain": "tomba.io",
	})
	if err == nil {
		fmt.Println(result)
	}
}
```

### Email Finder

Find the verified email address of any professional.

```go
package main

import (
	"fmt"

	"github.com/tomba-io/go/tomba"
)

func main() {
	client := tomba.New("ta_xxxxx", "ts_xxxxx")

	result, err := client.EmailFinder(tomba.Params{"domain": "asana.com", "full_name": "moskoz dustin"})
	if err == nil {
		fmt.Println(result)
	}
}
```

### Email Verifier

Verify the validity of any professional email address with the most complete email checker.

```go
package main

import (
	"fmt"

	"github.com/tomba-io/go/tomba"
)

func main() {
	tomba := tomba.New("ta_xxxxx", "ts_xxxxx")

	result, err := tomba.EmailVerifier("m@wordpress.org")
	if err == nil {
		fmt.Println(result)
	}
}
```

## Bulk Operations Overview

The Tomba Go SDK supports 10 different types of bulk operations:

| Bulk Type              | Purpose                          | Input Format      | Max Records    |
| ---------------------- | -------------------------------- | ----------------- | -------------- |
| **Author Finder**      | Find authors from blog URLs      | Text list or CSV  | 5,000 URLs     |
| **Company Enrichment** | Enrich company data from domains | Text list or CSV  | 15,000 domains |
| **Domain Search**      | Find emails in domains           | Text list         | 15,000 domains |
| **Email Enrichment**   | Enrich existing email addresses  | Text list or CSV  | 10,000 emails  |
| **Email Finder**       | Find emails from names + domains | CSV file required | 10,000 records |
| **Email Verifier**     | Verify email deliverability      | Text list or CSV  | 10,000 emails  |
| **LinkedIn Finder**    | Find emails from LinkedIn URLs   | Text list or CSV  | 10,000 URLs    |
| **Phone Finder**       | Find phone numbers from contacts | Text list or CSV  | 2,500 contacts |
| **Phone Validator**    | Validate phone numbers           | Text list or CSV  | 2,500 numbers  |
| **Similar Domain**     | Find similar companies           | Text list         | 500 domains    |

## Common Patterns

### 1. Basic Bulk Creation Pattern

```go
// Step 1: Create bulk
params := &models.BulkCreateParams{
    Name: "My Bulk Operation",
    List: "domain1.com\ndomain2.com\ndomain3.com",
    Sources: true,
    Verify: true,
}

response, err := client.CreateBulk(models.BulkTypeSearch, params)
if err != nil {
    log.Fatal(err)
}

// Step 2: Launch bulk
launchResp, err := client.LaunchBulk(models.BulkTypeSearch, *response.Data.ID)
if err != nil {
    log.Fatal(err)
}

// Step 3: Monitor progress
progress, err := client.GetBulkProgress(models.BulkTypeSearch, *response.Data.ID)
if err != nil {
    log.Fatal(err)
}

// Step 4: Download results
err = client.SaveBulkResults(models.BulkTypeSearch, *response.Data.ID, "./results.csv", "full")
if err != nil {
    log.Fatal(err)
}
```

### 2. File Upload Pattern

```go
// For operations requiring CSV files (Email Finder, Phone Validator)
params := &models.BulkFinderCreateParams{
    BulkCreateParams: models.BulkCreateParams{
        Name: "Email Finding from CSV",
        Delimiter: ",",
        Verify: true,
    },
    BulkFinderParams: models.BulkFinderParams{
        ColumnFirst: 1,  // First name column
        ColumnLast: 2,   // Last name column
        ColumnDomain: 3, // Domain column
        Skip: true,      // Skip header row
    },
}

response, err := client.CreateFinderBulk(params, "./contacts.csv")
```

### 3. Advanced Search Parameters

```go
// Domain Search with advanced filtering
searchParams := &models.BulkSearchCreateParams{
    BulkCreateParams: models.BulkCreateParams{
        Name: "Advanced Domain Search",
        List: "company1.com\ncompany2.com",
        Sources: true,
        Verify: true,
    },
    BulkSearchParams: models.BulkSearchParams{
        Maximum: "50", // Max emails per domain
        EmailType: models.BulkSearchParamsType{
            Type: "personal",
            PriorityType: "priority",
        },
        Department: models.BulkSearchParamsDepartment{
            Name: []string{"engineering", "marketing"},
            PriorityType: "only",
        },
    },
}

response, err := client.CreateSearchBulk(searchParams)
```

## Error Handling Best Practices

```go
func handleBulkOperation(client *tomba.Tomba) error {
    params := &models.BulkCreateParams{
        Name: "Test Bulk",
        List: "example.com",
    }

    // Create with error handling
    response, err := client.CreateBulk(models.BulkTypeSearch, params)
    if err != nil {
        return fmt.Errorf("failed to create bulk: %w", err)
    }

    if response.Data.ID == nil {
        return fmt.Errorf("bulk creation failed: no ID returned")
    }

    // Launch with retry logic
    bulkID := *response.Data.ID
    maxRetries := 3

    for i := 0; i < maxRetries; i++ {
        _, err = client.LaunchBulk(models.BulkTypeSearch, bulkID)
        if err == nil {
            break
        }

        if i == maxRetries-1 {
            return fmt.Errorf("failed to launch bulk after %d retries: %w", maxRetries, err)
        }

        time.Sleep(time.Duration(i+1) * time.Second)
    }

    return nil
}
```

## CSV File Format Examples

### Email Finder CSV

```text
FirstName,LastName,Domain,Company
John,Smith,stripe.com,Stripe
Jane,Doe,shopify.com,Shopify
Bob,Johnson,zoom.us,Zoom
```

### Phone Validator CSV

```text
PhoneNumber,Country
+1-555-123-4567,US
+44-20-7946-0958,GB
+33-1-42-86-83-26,FR
```

## Rate Limits and Best Practices

### Rate Limits

- **Email Verifier**: 50 emails per domain per 24 hours
- **API Requests**: Standard rate limiting applies
- **File Uploads**: Large files may take time to process

### Best Practices

1. **Use descriptive names** for easy bulk identification
2. **Enable verification** for higher quality results
3. **Monitor progress** regularly for large operations
4. **Handle errors gracefully** with retry logic
5. **Clean input data** before uploading
6. **Use appropriate bulk types** for your use case
7. **Archive completed bulks** to keep dashboard clean

## Complete Working Example

```go
package main

import (
    "fmt"
    "log"
    "os"
    "time"

    "github.com/tomba-io/go/tomba"
    "github.com/tomba-io/go/tomba/models"
)

func main() {
    // Initialize client
    client := tomba.NewClient(
        os.Getenv("TOMBA_API_KEY"),
        os.Getenv("TOMBA_API_SECRET"),
    )

    // Check account status
    account, err := client.Account()
    if err != nil {
        log.Fatal("Failed to connect to Tomba:", err)
    }

    fmt.Printf("Connected as: %s\n", account.Data.Owner.Email)
    fmt.Printf("Requests remaining: %d\n", account.Data.Requests.Available)

    // Create and run a bulk operation
    err = runBulkExample(client)
    if err != nil {
        log.Fatal("Bulk operation failed:", err)
    }
}

func runBulkExample(client *tomba.Tomba) error {
    // Create bulk
    params := &models.BulkCreateParams{
        Name: fmt.Sprintf("Example Bulk %s", time.Now().Format("2006-01-02 15:04")),
        List: "stripe.com\nshopify.com\nzoom.us",
        Sources: true,
        Verify: true,
    }

    response, err := client.CreateBulk(models.BulkTypeSearch, params)
    if err != nil {
        return err
    }

    bulkID := *response.Data.ID
    fmt.Printf("Created bulk with ID: %d\n", bulkID)

    // Launch bulk
    _, err = client.LaunchBulk(models.BulkTypeSearch, bulkID)
    if err != nil {
        return err
    }

    fmt.Println("Bulk launched successfully!")

    // Monitor progress
    for {
        progress, err := client.GetBulkProgress(models.BulkTypeSearch, bulkID)
        if err != nil {
            return err
        }

        fmt.Printf("Progress: %d%% (%d/%d processed)\n",
            progress.Progress, progress.Processed, progress.ProcessedEmail)

        if progress.Progress >= 100 {
            break
        }

        time.Sleep(5 * time.Second)
    }

    // Download results
    err = client.SaveBulkResults(models.BulkTypeSearch, bulkID, "./bulk_results.csv", "full")
    if err != nil {
        return err
    }

    fmt.Println("Results saved to ./bulk_results.csv")
    return nil
}
```

## Examples

### Get Account Information

```go
package main

import (
	"fmt"

	"github.com/tomba-io/go/tomba"
)

func main() {
	tomba := tomba.New("ta_xxxxx", "ts_xxxxx")

	result, err := tomba.Account()
	if err != nil {
		fmt.Println("Error : ", err)
		return
	}
	fmt.Print(result)
}
```

### Email Count

```go
package main

import (
	"fmt"

	"github.com/tomba-io/go/tomba"
)

func main() {
	tomba := tomba.New("ta_xxxxx", "ts_xxxxx")

	result, err := tomba.Count("tomba.io")
	if err != nil {
		fmt.Println("Error : ", err)
		return
	}
	fmt.Print(result)
}
```

### Finder Services

#### Author Finder

```go
package main

import (
	"fmt"

	"github.com/tomba-io/go/tomba"
)

func main() {
	tomba := tomba.New("ta_xxxxx", "ts_xxxxx")

	result, err := tomba.AuthorFinder("https://clearbit.com/blog/company-name-to-domain-api")
	if err != nil {
		fmt.Println("Error : ", err)
		return
	}
	fmt.Print(result)
}
```

#### LinkedIn Finder

```go
package main

import (
	"fmt"

	"github.com/tomba-io/go/tomba"
)

func main() {
	tomba := tomba.New("ta_xxxxx", "ts_xxxxx")

	result, err := tomba.LinkedinFinder("https://www.linkedin.com/in/alex-maccaw-ab592978")
	if err != nil {
		fmt.Println("Error : ", err)
		return
	}
	fmt.Print(result)
}
```

### Email Enrichment

```go
package main

import (
	"fmt"

	"github.com/tomba-io/go/tomba"
)

func main() {
	tomba := tomba.New("ta_xxxxx", "ts_xxxxx")

	result, err := tomba.Enrichment("b.mohamed@tomba.io")
	if err != nil {
		fmt.Println("Error : ", err)
		return
	}
	fmt.Print(result)
}
```

### Email Sources

```go
package main

import (
	"fmt"

	"github.com/tomba-io/go/tomba"
)

func main() {
	client := tomba.New("ta_xxxxx", "ts_xxxxx")
	result, err := client.Sources("ab@tomba.io")
	if err != nil {
		fmt.Println("Error : ", err)
		return
	}
	fmt.Print(result.Sources)
}
```

### Domain and Company Status

#### Domain Status

```go
package main

import (
	"fmt"

	"github.com/tomba-io/go/tomba"
)

func main() {
	tomba := tomba.New("ta_xxxxx", "ts_xxxxx")

	result, err := tomba.Status("gmail.com")
	if err != nil {
		fmt.Println("Error : ", err)
		return
	}
	fmt.Print(result)
}
```

#### Similar Domains

```go
package main

import (
	"fmt"

	"github.com/tomba-io/go/tomba"
)

func main() {
	client := tomba.New("", "")
	result, err := client.SimilarDomains("tomba.io")
	if err != nil {
		fmt.Println("Error : ", err)
		return
	}
	fmt.Println("Total Results: ", len(result.Data))
	for _, domain := range result.Data {
		name := ""
		if domain.Name != nil {
			name = *domain.Name
		}
		fmt.Println("Domain: ", name, " - WebsiteURL: ", domain.WebsiteURL)
	}
}
```

### Activity Logs

```go
package main

import (
	"fmt"

	"github.com/tomba-io/go/tomba"
)

func main() {
	tomba := tomba.New("ta_xxxxx", "ts_xxxxx")

	result, err := tomba.Logs()
	if err != nil {
		fmt.Println("Error : ", err)
		return
	}
	fmt.Print(result)
}
```

### Usage Statistics

```go
package main

import (
	"fmt"

	"github.com/tomba-io/go/tomba"
)

func main() {
	tomba := tomba.New("ta_xxxxx", "ts_xxxxx")

	result, err := tomba.Usage()
	if err != nil {
		fmt.Println("Error : ", err)
		return
	}
	fmt.Print(result)
}
```

### Complete Bulk Search Example

```go
package main

import (
	"fmt"
	"log"
	"time"

	"github.com/tomba-io/go/tomba"
	"github.com/tomba-io/go/tomba/models"
)

func main() {
	client := tomba.New("ta_xx", "ts_xxx")

	// Create a new search bulk
	searchParams := &models.BulkSearchCreateParams{
		BulkCreateParams: models.BulkCreateParams{
			Name:   "My Search Bulk",
			List:   "tomba.io\ndaily.dev",
			Verify: false,
		},
		BulkSearchParams: models.BulkSearchParams{
			Maximum: "10",
			EmailType: models.BulkSearchParamsType{
				Type:         "all",
				PriorityType: "only",
			},
			Department: models.BulkSearchParamsDepartment{
				Name:         []string{"executive"}, // Example department names
				PriorityType: "only",
			},
		},
	}

	result, err := client.CreateSearchBulk(searchParams)
	if err != nil {
		log.Fatal(err)
	}
	if result.Data.ID != nil {
		fmt.Printf("Created bulk with ID: %d\n", *result.Data.ID)

		// Launch the bulk
		_, err = client.LaunchBulk(models.BulkTypeSearch, *result.Data.ID)
		if err != nil {
			log.Fatal(err)
		}

		// Get progress
		progress, err := client.GetBulkProgress(models.BulkTypeSearch, *result.Data.ID)
		if err != nil {
			log.Fatal(err)
		}

		// Wait for the bulk to complete
		for progress.Progress < 100 {
			fmt.Printf("Waiting for bulk to complete... Current progress: %d%%\n", progress.Progress)
			time.Sleep(1 * time.Second)
			progress, err = client.GetBulkProgress(models.BulkTypeSearch, *result.Data.ID)
			if err != nil {
				log.Fatal(err)
			}
		}

		// Download results when completed
		downloadData, err := client.DownloadBulk(models.BulkTypeSearch, *result.Data.ID, &models.BulkDownloadParams{
			Type: "full",
		})
		if err != nil {
			log.Fatal(err)
		}

		// Save the downloaded data to a file
		if len(downloadData) != 0 {
			fmt.Printf("Downloaded %d bytes of results\n", len(downloadData))

			// Save full results
			err = client.SaveBulkResults(models.BulkTypeSearch, *result.Data.ID, searchParams.Name+".csv", "full")
			if err != nil {
				log.Printf("Error saving full results: %v", err)
			} else {
				fmt.Printf("✅ Full results saved to: %s\n", searchParams.Name+".csv")
			}
		} else {
			log.Fatal("No data downloaded, the bulk might not be completed yet or no results found.")
		}
	}
}
```

For more sample codes, check the [**examples/**](https://github.com/tomba-io/go/tree/master/examples) folder.
