DocsSDKSDK Go

SDK Go

Le SDK Go arrive bientôt : en attendant, appelez l'API REST Coffrify directement depuis Go avec net/http et context.

SDK3 min de lectureMis à jour le 10 juin 2026
Télécharger en PDF

Cette page décrit comment intégrer Coffrify depuis une application Go. Un SDK Go officiel est en préparation. En attendant sa publication, l'API REST v1 reste pleinement accessible depuis Go avec la bibliothèque standard net/http et le package context. Les exemples ci-dessous couvrent le parcours complet : créer un transfert, téléverser les fichiers vers les URLs signées, lister vos transferts, et un mot sur les webhooks. Tout ce que fera le futur SDK, vous pouvez le faire dès aujourd'hui en HTTP.

Prérequis

Vous avez besoin d'une clé API depuis votre espace Coffrify. Utilisez une clé de test cof_test_… pour développer, et une clé cof_live_… en production. La création d'un transfert requiert le scope transfers:write ; la liste requiert transfers:read. Toutes les requêtes ciblent la base https://api.coffrify.com/v1 et s'authentifient avec l'en-tête Authorization: Bearer <clé>.

Pour isoler votre clé du code source, lisez-la depuis l'environnement, par exemple via os.Getenv("COFFRIFY_API_KEY"). Pensez à définir un http.Client avec un Timeout, et à propager un context.Context sur chaque appel afin de pouvoir annuler une requête.

Créer un transfert

POST/v1/transfersCrée un transfert et renvoie les URLs de téléversement

Vous décrivez les fichiers (name, size, mime_type) et, optionnellement, une durée de validité, un destinataire et un titre. La réponse contient l'objet transfer (avec id, short_code, share_url, expires_at), un tableau upload_urls (une entrée par fichier, avec file_id, url et les headers à renvoyer), ainsi que share_url que vous partagez avec le destinataire. Le contenu est chiffré côté serveur par défaut, et les données sont hébergées dans l'Union européenne.

package main
 
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
"os"
"time"
)
 
const baseURL = "https://api.coffrify.com/v1"
 
type fileSpec struct {
Name string `json:"name"`
Size int64 `json:"size"`
MimeType string `json:"mime_type"`
}
 
type createTransferReq struct {
Files []fileSpec `json:"files"`
ExpiresInHours int `json:"expires_in_hours,omitempty"`
Recipient string `json:"recipient,omitempty"`
TransferTitle string `json:"transfer_title,omitempty"`
}
 
type createTransferResp struct {
Transfer struct {
ID string `json:"id"`
ShortCode string `json:"short_code"`
Status string `json:"status"`
ShareURL string `json:"share_url"`
ExpiresAt string `json:"expires_at"`
} `json:"transfer"`
UploadURLs []struct {
FileID string `json:"file_id"`
URL string `json:"url"`
Headers map[string]string `json:"headers"`
} `json:"upload_urls"`
ShareURL string `json:"share_url"`
}
 
func createTransfer(ctx context.Context, client *http.Client, apiKey string) (*createTransferResp, error) {
payload := createTransferReq{
Files: []fileSpec{
{Name: "contrat.pdf", Size: 284512, MimeType: "application/pdf"},
},
ExpiresInHours: 72,
Recipient: "client@exemple.com",
TransferTitle: "Contrat signe",
}
 
body, err := json.Marshal(payload)
if err != nil {
return nil, err
}
 
req, err := http.NewRequestWithContext(ctx, http.MethodPost, baseURL+"/transfers", bytes.NewReader(body))
if err != nil {
return nil, err
}
req.Header.Set("Authorization", "Bearer "+apiKey)
req.Header.Set("Content-Type", "application/json")
// Idempotence : rejouer la meme requete ne cree pas un doublon.
req.Header.Set("Idempotency-Key", "transfer-contrat-2026-06-10")
 
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
 
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
return nil, fmt.Errorf("coffrify: statut inattendu %d", resp.StatusCode)
}
 
var out createTransferResp
if err := json.NewDecoder(resp.Body).Decode(&out); err != nil {
return nil, err
}
return &out, nil
}
 
func main() {
apiKey := os.Getenv("COFFRIFY_API_KEY")
client := &http.Client{Timeout: 30 * time.Second}
 
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
 
t, err := createTransfer(ctx, client, apiKey)
if err != nil {
panic(err)
}
fmt.Println("Lien de partage :", t.ShareURL)
}

Téléverser les fichiers

Pour chaque entrée de upload_urls, envoyez le contenu du fichier en PUT vers l'url fournie, en réémettant exactement les headers retournés. Ces URLs sont signées et temporaires : téléversez sans tarder après la création. Une fois tous les fichiers en place, le transfert est prêt et vous pouvez communiquer share_url.

// uploadFile envoie le contenu vers une URL signee renvoyee dans upload_urls.
// On reemet tous les headers fournis par l'API tels quels.
func uploadFile(ctx context.Context, client *http.Client, url string, headers map[string]string, content []byte) error {
req, err := http.NewRequestWithContext(ctx, http.MethodPut, url, bytes.NewReader(content))
if err != nil {
return err
}
for k, v := range headers {
req.Header.Set(k, v)
}
 
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
 
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return fmt.Errorf("upload: statut %d", resp.StatusCode)
}
return nil
}
 
// Apres createTransfer : on pousse chaque fichier vers son URL signee.
// content provient de os.ReadFile("contrat.pdf") par exemple.
for _, u := range t.UploadURLs {
if err := uploadFile(ctx, client, u.URL, u.Headers, content); err != nil {
panic(err)
}
}
fmt.Println("Transfert pret :", t.Transfer.ShortCode)

Lister les transferts

GET/v1/transfersListe paginée par curseur

La liste est paginée par curseur. Passez limit (100 au maximum) et, pour la page suivante, le curseur renvoyé par la réponse précédente. Récupérer ou supprimer un transfert précis se fait sur /v1/transfers/{id} en GET ou DELETE.

func listTransfers(ctx context.Context, client *http.Client, apiKey, cursor string) (*http.Response, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, baseURL+"/transfers", nil)
if err != nil {
return nil, err
}
req.Header.Set("Authorization", "Bearer "+apiKey)
 
q := req.URL.Query()
q.Set("limit", "50")
if cursor != "" {
q.Set("cursor", cursor)
}
req.URL.RawQuery = q.Encode()
 
return client.Do(req)
}

Gérer les erreurs

Les erreurs suivent un format stable. Décodez le corps pour récupérer le code, le message lisible et le request_id (utile pour le support). Vérifiez d'abord le resp.StatusCode, puis décodez ce corps lorsque le statut n'est pas un succès.

{
"error": {
"code": "invalid_request",
"message": "Le champ files est requis.",
"request_id": "req_9f2c1a"
}
}

Webhooks

Coffrify peut notifier votre service lorsqu'un évènement survient, par exemple transfer.downloaded. Vous créez un endpoint via POST /v1/webhooks ; le secret de signature (whsec_…) n'est affiché qu'une seule fois. À la réception, votre serveur Go doit vérifier la signature avant de traiter la charge utile, en recalculant un HMAC-SHA256 à partir du secret et en comparant avec l'en-tête webhook-signature (format Standard Webhooks), dans une tolérance de 5 minutes. La mécanique exacte des en-têtes figure dans la référence des webhooks.


Lorsque le SDK Go sera disponible, cette page proposera l'installation par go get, un client typé et des méthodes idiomatiques (création, liste, récupération et suppression de transferts, webhooks et réceptions) en remplacement des appels HTTP manuels ci-dessus. D'ici là, les exemples net/http restent la voie officielle et resteront valables.

Cette page vous a-t-elle aidé ?
Anonyme, dédupliqué 24h par signature locale.