Go icon

Go Quick Start Guide

Get started with FacePing's face recognition API using Go

Prerequisites

Setup

First, create a new Go project:

mkdir faceping-demo
cd faceping-demo
go mod init faceping-demo

Create .env file:

FACEPING_API_KEY=your_api_key_here

Install required package:

go get github.com/joho/godotenv

Step 1: Create Face Group

Create a new file create_group.go:

package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"github.com/joho/godotenv"
)

func createGroup(groupName string) error {
	// Load API key from environment
	if err := godotenv.Load(); err != nil {
		return fmt.Errorf("error loading .env file: %w", err)
	}

	apiKey := os.Getenv("FACEPING_API_KEY")
	url := fmt.Sprintf("https://api.faceping.ai/groups/%s", groupName)

	// Create request
	req, err := http.NewRequest("POST", url, nil)
	if err != nil {
		return fmt.Errorf("error creating request: %w", err)
	}

	// Add headers
	req.Header.Add("Authorization", "Bearer "+apiKey)

	// Send request
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("error sending request: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("error creating group: %s", resp.Status)
	}

	fmt.Println("Group created successfully")
	return nil
}

func main() {
	err := createGroup("my-group")
	if err != nil {
		log.Fatal(err)
	}
}

Step 2: Upload Face Image

Create a new file upload_face.go:

package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"
	"github.com/joho/godotenv"
)

func uploadFace(groupName, imagePath string) error {
	if err := godotenv.Load(); err != nil {
		return fmt.Errorf("error loading .env file: %w", err)
	}

	apiKey := os.Getenv("FACEPING_API_KEY")
	url := fmt.Sprintf("https://api.faceping.ai/groups/%s/faces", groupName)

	// Open file
	file, err := os.Open(imagePath)
	if err != nil {
		return fmt.Errorf("error opening file: %w", err)
	}
	defer file.Close()

	// Create multipart form
	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)

	part, err := writer.CreateFormFile("image", filepath.Base(imagePath))
	if err != nil {
		return fmt.Errorf("error creating form file: %w", err)
	}

	_, err = io.Copy(part, file)
	if err != nil {
		return fmt.Errorf("error copying file: %w", err)
	}

	writer.Close()

	// Create request
	req, err := http.NewRequest("POST", url, body)
	if err != nil {
		return fmt.Errorf("error creating request: %w", err)
	}

	// Add headers
	req.Header.Add("Authorization", "Bearer "+apiKey)
	req.Header.Add("Content-Type", writer.FormDataContentType())

	// Send request
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("error sending request: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("error uploading face: %s", resp.Status)
	}

	fmt.Println("Face uploaded successfully")
	return nil
}

func main() {
	err := uploadFace("my-group", "path/to/face.jpg")
	if err != nil {
		log.Fatal(err)
	}
}

Step 3: Search for Faces

Create a new file search_faces.go:

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"
	"github.com/joho/godotenv"
)

type MatchResult struct {
	Score float64 `json:"score"`
}

type SearchResponse struct {
	Matches []MatchResult `json:"matches"`
}

func searchFaces(groupName, imagePath string) ([]MatchResult, error) {
	if err := godotenv.Load(); err != nil {
		return nil, fmt.Errorf("error loading .env file: %w", err)
	}

	apiKey := os.Getenv("FACEPING_API_KEY")
	url := fmt.Sprintf("https://api.faceping.ai/groups/%s/search", groupName)

	// Open file
	file, err := os.Open(imagePath)
	if err != nil {
		return nil, fmt.Errorf("error opening file: %w", err)
	}
	defer file.Close()

	// Create multipart form
	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)

	part, err := writer.CreateFormFile("image", filepath.Base(imagePath))
	if err != nil {
		return nil, fmt.Errorf("error creating form file: %w", err)
	}

	_, err = io.Copy(part, file)
	if err != nil {
		return nil, fmt.Errorf("error copying file: %w", err)
	}

	writer.Close()

	// Create request
	req, err := http.NewRequest("POST", url, body)
	if err != nil {
		return nil, fmt.Errorf("error creating request: %w", err)
	}

	// Add headers
	req.Header.Add("Authorization", "Bearer "+apiKey)
	req.Header.Add("Content-Type", writer.FormDataContentType())

	// Send request
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("error sending request: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("error searching faces: %s", resp.Status)
	}

	// Parse response
	var searchResp SearchResponse
	if err := json.NewDecoder(resp.Body).Decode(&searchResp); err != nil {
		return nil, fmt.Errorf("error decoding response: %w", err)
	}

	fmt.Printf("Found %d matches\n", len(searchResp.Matches))
	return searchResp.Matches, nil
}

func main() {
	matches, err := searchFaces("my-group", "path/to/search-face.jpg")
	if err != nil {
		log.Fatal(err)
	}

	for _, match := range matches {
		fmt.Printf("Match Score: %f\n", match.Score)
	}
}

Security Notes

  • Images are immediately discarded after vector conversion
  • Face vectors cannot be reverse-engineered into images
  • Always use HTTPS for all API calls
  • Store your API keys in environment variables (.env file)

Ready to get started?

Take a look at the API documentation
API docs