Skip to content
Pidgely Docs

Guides

Contacts, segments & audiences

Store contacts with typed properties, group them in segments for broadcasts, and keep unsubscribes in sync with the suppression list. Legacy audiences are supported.

View as Markdown

Contacts are the people you send broadcasts to:

  • Contacts are global to your account and unique by email.
  • Segments are named groups. A contact can belong to any number of segments.
  • Audiences are the legacy name for segments, kept so older code keeps working.

Contacts

Node.js
import { Pidgely } from 'pidgely';

const pidgely = new Pidgely(process.env.PIDGELY_API_KEY);

const { data, error } = await pidgely.contacts.create({
  email: 'steve@example.com',
  firstName: 'Steve',
  lastName: 'Wozniak',
  properties: {
    plan: 'pro',
    seats: 5,
    beta: true,
  },
  segments: [
    {
      id: '0199d7f5-9a3e-7d4b-a1c2-7e5f0b3d6c48',
    },
  ],
});
console.log(data ?? error);
Python
import os
import pidgely

pidgely.api_key = os.environ["PIDGELY_API_KEY"]

result = pidgely.Contacts.create({
    "email": "steve@example.com",
    "first_name": "Steve",
    "last_name": "Wozniak",
    "properties": {
        "plan": "pro",
        "seats": 5,
        "beta": True,
    },
    "segments": [
        {
            "id": "0199d7f5-9a3e-7d4b-a1c2-7e5f0b3d6c48",
        },
    ],
})
print(result)
PHP
<?php

require __DIR__ . '/vendor/autoload.php';

$pidgely = Pidgely::client(getenv('PIDGELY_API_KEY'));

$result = $pidgely->contacts->create([
    'email' => 'steve@example.com',
    'first_name' => 'Steve',
    'last_name' => 'Wozniak',
    'properties' => [
        'plan' => 'pro',
        'seats' => 5,
        'beta' => true,
    ],
    'segments' => [
        [
            'id' => '0199d7f5-9a3e-7d4b-a1c2-7e5f0b3d6c48',
        ],
    ],
]);
var_dump($result);
Go
package main

import (
	"context"
	"fmt"
	"os"

	"github.com/pidgely/pidgely-go"
)

func main() {
	ctx := context.Background()
	client := pidgely.NewClient(os.Getenv("PIDGELY_API_KEY"))

	result, err := client.Contacts.Create(ctx, &pidgely.CreateContactRequest{
		Email:      "steve@example.com",
		FirstName:  "Steve",
		LastName:   "Wozniak",
		Properties: map[string]any{
		"plan":  "pro",
		"seats": 5,
		"beta":  true,
	},
		Segments:   []pidgely.Segment{
		{
			Id: "0199d7f5-9a3e-7d4b-a1c2-7e5f0b3d6c48",
		},
	},
	})
	if err != nil {
		panic(err)
	}
	fmt.Println(result)
}
Ruby
require "pidgely"

Pidgely.api_key = ENV["PIDGELY_API_KEY"]

result = Pidgely::Contacts.create({
  email: "steve@example.com",
  first_name: "Steve",
  last_name: "Wozniak",
  properties: {
    plan: "pro",
    seats: 5,
    beta: true
  },
  segments: [
    {
      id: "0199d7f5-9a3e-7d4b-a1c2-7e5f0b3d6c48"
    }
  ]
})
puts result
cURL
curl -X POST 'https://api.pidgely.com/contacts' \
  -H "Authorization: Bearer $PIDGELY_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
  "email": "steve@example.com",
  "first_name": "Steve",
  "last_name": "Wozniak",
  "properties": {
    "plan": "pro",
    "seats": 5,
    "beta": true
  },
  "segments": [
    {
      "id": "0199d7f5-9a3e-7d4b-a1c2-7e5f0b3d6c48"
    }
  ]
}'
  • POST /contacts is an upsert: posting an email that already exists updates that contact.
  • first_name and last_name are up to 200 characters.
  • Properties: up to 100 per contact. Keys match ^[A-Za-z_][A-Za-z0-9_]{0,49}$; values are strings (up to 2,000 characters), numbers or booleans. Set a key to null to delete it. Reads return each property as { "value": …, "type": "string" | "number" | "boolean" }.
  • Retrieve, update and delete by id or email: GET /contacts/steve@example.com works.
  • topics is not supported yet and is rejected.

Unsubscribes and the suppression list

unsubscribed and the suppression list stay in sync, both ways:

Change Effect
The contact clicks the unsubscribe link of a broadcast An unsubscribe suppression is added and the contact becomes unsubscribed: true
You set unsubscribed: true An unsubscribe suppression is added
You set unsubscribed: false The unsubscribe suppression is removed (bounce and complaint suppressions are never removed this way)
You remove an unsubscribe suppression The contact becomes subscribed again
You create a contact whose address already has an unsubscribe suppression The contact starts as unsubscribed

Suppressions are account-wide: an address that unsubscribed from broadcasts is also skipped by transactional sends. Deleting a contact keeps its suppression.

Segments

Create a segment, then add contacts to it:

Node.js
import { Pidgely } from 'pidgely';

const pidgely = new Pidgely(process.env.PIDGELY_API_KEY);

const { data, error } = await pidgely.segments.create({
  name: 'Newsletter',
});
console.log(data ?? error);
Python
import os
import pidgely

pidgely.api_key = os.environ["PIDGELY_API_KEY"]

result = pidgely.Segments.create({
    "name": "Newsletter",
})
print(result)
PHP
<?php

require __DIR__ . '/vendor/autoload.php';

$pidgely = Pidgely::client(getenv('PIDGELY_API_KEY'));

$result = $pidgely->segments->create([
    'name' => 'Newsletter',
]);
var_dump($result);
Go
package main

import (
	"context"
	"fmt"
	"os"

	"github.com/pidgely/pidgely-go"
)

func main() {
	ctx := context.Background()
	client := pidgely.NewClient(os.Getenv("PIDGELY_API_KEY"))

	result, err := client.Segments.Create(ctx, &pidgely.CreateSegmentRequest{
		Name: "Newsletter",
	})
	if err != nil {
		panic(err)
	}
	fmt.Println(result)
}
Ruby
require "pidgely"

Pidgely.api_key = ENV["PIDGELY_API_KEY"]

result = Pidgely::Segments.create({
  name: "Newsletter"
})
puts result
cURL
curl -X POST 'https://api.pidgely.com/segments' \
  -H "Authorization: Bearer $PIDGELY_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "Newsletter"
}'
Node.js
import { Pidgely } from 'pidgely';

const pidgely = new Pidgely(process.env.PIDGELY_API_KEY);

const { data, error } = await pidgely.contacts.segments.add({
  email: 'steve@example.com',
  segmentId: '0199d7f5-9a3e-7d4b-a1c2-7e5f0b3d6c48',
});
console.log(data ?? error);
Python
import os
import pidgely

pidgely.api_key = os.environ["PIDGELY_API_KEY"]

result = pidgely.Contacts.Segments.add({
    "email": "steve@example.com",
    "segment_id": "0199d7f5-9a3e-7d4b-a1c2-7e5f0b3d6c48",
})
print(result)
PHP
<?php

require __DIR__ . '/vendor/autoload.php';

$pidgely = Pidgely::client(getenv('PIDGELY_API_KEY'));

$result = $pidgely->contacts->segments->add([
    'email' => 'steve@example.com',
    'segment_id' => '0199d7f5-9a3e-7d4b-a1c2-7e5f0b3d6c48',
]);
var_dump($result);
Go
package main

import (
	"context"
	"fmt"
	"os"

	"github.com/pidgely/pidgely-go"
)

func main() {
	ctx := context.Background()
	client := pidgely.NewClient(os.Getenv("PIDGELY_API_KEY"))

	result, err := client.Contacts.Segments.Add(ctx, "steve@example.com", "0199d7f5-9a3e-7d4b-a1c2-7e5f0b3d6c48")
	if err != nil {
		panic(err)
	}
	fmt.Println(result)
}
Ruby
require "pidgely"

Pidgely.api_key = ENV["PIDGELY_API_KEY"]

result = Pidgely::Contacts::Segments.add({
  email: "steve@example.com",
  segment_id: "0199d7f5-9a3e-7d4b-a1c2-7e5f0b3d6c48"
})
puts result
cURL
curl -X POST 'https://api.pidgely.com/contacts/steve@example.com/segments/0199d7f5-9a3e-7d4b-a1c2-7e5f0b3d6c48' \
  -H "Authorization: Bearer $PIDGELY_API_KEY"
  • List a segment's members with GET /segments/{id}/contacts or GET /contacts?segment_id=….
  • Removing a contact from a segment keeps the contact. Deleting a segment keeps its contacts.
  • Segment names are 1–200 characters.

Audiences (legacy)

The /audiences endpoints are aliases of segments over the same global contacts, and broadcasts accept audience_id as an alias of segment_id.

Webhooks

Contact changes emit contact.created, contact.updated and contact.deleted webhooks with the contact's id, email, names, unsubscribed and timestamps.