Welcome to the Pigeon API documentation. This guide will help you integrate Pigeon's features into your applications to manage customers, content, subscriptions, and more.
Getting Started
The Pigeon API follows REST principles and provides data in JSON format for all responses, including errors. All requests must be made over HTTPS for security purposes - requests made over HTTP will fail.
Authentication
To access the API, you must include your secret API key in all requests.
How to get your API key:
- Contact Pigeon support to generate your unique API keys
- Dashboard management of API keys will be available soon
Important security notes:
- Never share your API keys publicly
- All API requests without proper authentication will fail
- Always use HTTPS for API calls
Official Libraries
We provide official libraries to make integration easier:
- PHP SDK - Our officially supported PHP library
If you've developed a library for Pigeon in another language and would like it listed here, please contact us. We're happy to link to community-supported implementations.
HTTP Status Codes
200 - OK | Everything worked as expected. |
401 - Unauthorized | No valid API key provided. |
500, 502, 503, 504 - Server Errors | Server errors (very rare) |
Content API
Get Content
Endpoint /api/cnd/get
The content endpoint allows you to get access to blog posts and galleries.
Parameters
id | Blog id (required) |
detail | Default: 0 (optional) 0 == abridged data, 1 == Gets the full unabridged body detail |
filters |
Array (optional) |
filters[limit] | Default: 200 (max) 0 == None, 1 == Card, 2 == Invoice or bill to pay later |
filters[page] | Default: 1 For pagination of data sets in blocks the size defined by limit above |
filters[date_range_published] | Date format: array Filter based on the date the content item was published. Y-m-d hh:mm:ss (e.g., [2020-08-23 00:00:00, 2020-08-30 23:59:59] ) array[0] == start_date, array[1] == end_date |
filters[date_range_added] | Date format: array Filter based on the date the content item was added. Y-m-d hh:mm:ss (e.g., [2020-08-23 00:00:00, 2020-08-30 23:59:59] ) array[0] == start_date, array[1] == end_date |
Example Request
GET /api/cnd/get?client_id=your_client_id&api_key=your_secret_api_key&id=1&detail=1&filters[limit]=1&filters[date_range_published][0]=2021-01-01 00:00:00&filters[date_range_published][1]=2021-02-01 23:59:59
JSON Response
{
"success":true,
"results":
[{
"id": "94422",
"version_id": "313919",
"title": "Pigeon Paywall API",
"subtitle": null,
"excerpt": "Pigeon is a solution for your paid access needs.",
"body": "<div>All the power you need in one solution to better monetize your content.</div>",
"author": "CJ",
"publish_date": {
"date": "2021-02-01 11:19:01.000000",
"timezone_type": 3,
"timezone": "America\/Indiana\/Indianapolis"
},
"type": "1",
"comment_count": "0",
"order_index": "0",
"file_hash": null,
"enabled": "1",
"image_node_id": "124953",
"default_image_id": "813163",
"default_image_actual_width": "254",
"default_image_actual_height": "300",
"default_image_size": "16147",
"default_image_credit": null,
"default_image_caption": "",
"default_image_added": "1612203621",
"extension": "jpg",
"default_image": "https:\/\/url-to-cdn.com\/89f09e44865a9f83b6cb6bf0a1446fc3.jpg",
"permalink": "https:\/\/pigeonpay.com\/"
}]
}
Customer API
Find Customer
Endpoint /api/customer
You can retrieve customer information by ID.
Parameters
id | Customer ID |
Example Request
GET /api/customer?client_id=your_client_id&api_key=your_secret_api_key&id=6e4a8f33oreg8jd0ln1
JSON Response
{
"success": true,
"customer": {
"email": "nick@sabramedia.com",
"display_name": "Nick Johnson",
"sex": "",
"dob": "",
"first_name": "Nick",
"last_name": "Johnson",
"group_type": false,
"id": "6e4a8f33oreg8jd0ln1",
"parent": [],
"access": true,
"plans": [
{
"access_id": 3,
"access_tag": "default",
"name": "Print + Digital Bundle Monthly $7.00 subscription",
"start": "2018-05-01",
"type": 1
}
]
}
}
Customer Login
Endpoint /api/customer/login
Authenticate a customer by email and password.
When to use this endpoint:
- For native mobile app authentication
- When implementing custom session handling
- For integrating Pigeon user data with your internal user database
Note: For most web applications, we recommend using our JavaScript plugin or SDK tools, which automatically handle authentication.
In addition to the API authentication credentials you need to pass the user's email and password to this endpoint to determine if they are a registered user. If there is a match, then the customer details are returned. At this point you can handle your sessions locally and use the customer id to grab user details to determine user access status. If the user credentials don't match, the response status will fail and send back a reason message.
Authentication Flow
-
Post login credentials to authenticate the customer.
CURL -X POST {pigeon_domain_here}/api/customer/login -H "Content-Type: application/json" -d '{"client_id":"your_client_id","api_key":"your_api_key","email":"pigeon@sabramedia.com","password":"customer_password"}'
-
Store the returned customer ID in a local session. Notice the
customer.id
in the example JSON response below:{ "success": true, "customer": { "id": "6e4a8focoe8jd0ln1", "email": "nick@sabramedia.com", "display_name": "Nick Johnson", "first_name": "Nick", "last_name": "Johnson", "group_type": true, "parent": [], "access": true, "plans": [ { "access_id": 1, "term_id": 3, "access_tag": "default", "name": "Premium Digital Access Monthly", "start": "2018-08-23", "type": 1 } ], "password_set_url": "http:\/\/staging.sabramedia.com\/password-reset?h=9e2245d765f52af89e2d50cd77621dcb", "sessions": 2, "sso_link": "{pigeon_domain_here}?psso=Y3VzdG9tZXJfaWQ9NmU0YThmb2NvZThqZDBsbjEmcmQ9aHR0cCUzQSUyRiUyRnN0YWdpbmcuc2FicmFtZWRpYS5jb20=&sig=7a0994e3c224c7cb5565193db04d1d2c6c7c02067287b31066b588159658de62" }, "session": { "id": 79994, "hash": "d3659496ec0fb6acadb089091ea51470", "fingerprint": null, "set_method": 2, "ip_address": "192.0.0.1", "timeout": 1548608580, "domain": "sabramedia.com" }, "token": "d3659496ec0fb6acadb089091ea51470" }
-
Query our servers with their
customer.id
using the find verb (example below). Do this on subsequent calls to your service. This will keep continuity with the customer's access status in our database.GET /api/customer?client_id=your_client_id&api_key=your_secret_api_key&id=6e4a8f33oreg8jd0ln1
No paywall rules are factored in the access check. This is fine. In most cases you will just check the access boolean (true or false). If true then they have an enabled account (
customer.access == true
). You can develop additional access logic by iterating over the plan(s) to decide what content a person has access to based on their plan. If customer access is false, then you will need to link them to their user account in a browser via the customer's returnedcustomer.sso_link
. From there they can mange their access.</p -
When a session expires or user logs out, restart the authentication process.
Search Customers
Endpoint /api/customer/search
Find customers based on various search criteria.
Parameters
search | Searches customer name, company name, email, phone, postal code, and third party id (required) |
Example Request
GET /api/customer/search?client_id=your_client_id&api_key=your_secret_api_key&search=pigeon@sabramedia.com
JSON Response
{
"success": true,
"results": [
{
"id": "xenblda7vh6l6qrs679",
"display_name": "",
"full_name": "",
"email": "pigeon@sabramedia.com",
"status": "0",
"authorized": "0",
"addresses": []
}
]
}
Create Customer
Endpoint /api/customer/create
Create a new customer account.
Parameters
display_name | Customer's full name (optional) |
Customer's email (required) | |
password | Customer's password (optional) |
send_notice | Trigger the welcome notice. Default is TRUE. (optional) |
internal_id | ID of third party system. Can be used to relate the Pigeon customer to third party id. Is visible on profile tab and exports. |
Note: Data must be a JSON-encoded object and sent as application/x-www-form-urlencoded in the request.
CURL POST Example
CURL -X POST {pigeon_domain_here}/api/customer -H "Content-Type: application/json" -d '{"client_id":"your_client_id","api_key":"your_api_key","display_name":"Nick Johnson","email":"pigeon@sabramedia.com"}'
JSON Response
{
"success": true,
"customer": {
"email": "pigeon@sabramedia.com",
"display_name": "Nick Johnson",
"sex": null,
"dob": null,
"first_name": "",
"last_name": null,
"group_type": false,
"id": "xenblda7vh6l6qrs679",
"parent": [],
"access": false,
"plans": null
}
}
Add Plan to Customer
Endpoint /api/customer/add_plan
Add a subscription plan to a customer account.
Parameters
customer_id | Customer's id returned in get or create requests (required) |
plan_number | A known plan number (required) |
plan_type | Default: 1 (optional) 1 == subscription, 2 == subscription trial |
payment_method | Default: 1 (optional) 0 == None, 1 == Card, 2 == Invoice or bill to pay later |
send_notice | Default: TRUE (optional) If true then the order notice is sent. If false, then it's not sent. |
Note: Currently, payment method details cannot be provided via the API. When payment_method is set to 1 (Card), the customer will be prompted to activate their account with payment details.
CURL POST Example
CURL -X POST {pigeon_domain_here}/api/customer/add_plan -H "Content-Type: application/json" -d '{"client_id":"your_client_id","api_key":"your_api_key","customer_id":"xenblda7vh6l6qrs679","plan_number":"12345","plan_type":"1","payment_method":"1"}'
JSON Response
{
"success": true,
"customer": {
"email": "nick@sabramedia.com",
"display_name": "Nick Johnson",
"sex": "",
"dob": "",
"first_name": "Nick",
"last_name": "Johnson",
"group_type": false,
"id": "6e4a8f33oreg8jd0ln1",
"parent": [],
"access": true,
"plans": [
{
"access_id": 3,
"access_tag": "default",
"name": "Print + Digital Bundle Monthly $7.00 subscription",
"start": "2018-05-01",
"type": 1
}
]
}
}
Subscription API
Subscription Summary
Endpoint: /api/subscription/summary
Parameters
date_range | Default: Withing the last month of yesterday (optional) Date format: Y-m-d (e.g., 2018-08-23) array[0] == start_date, array[1] == end_date |
Example Request
GET /api/subscription/summary?client_id=your_client_id&api_key=your_secret_api_key
Example Request - with optional date range filter
GET /api/subscription/summary?client_id=your_client_id&api_key=your_secret_api_key&date_range[]=2018-04-01&date_range[]=2018-04-28
JSON Response
{
"success": true,
"date_range": {
"start": {
"date": "2018-04-01 00:00:00",
"timezone_type": 3,
"timezone": "America\/Chicago"
},
"end": {
"date": "2018-04-28 23:59:59",
"timezone_type": 3,
"timezone": "America\/Chicago"
}
},
"results": [
{
"product_id": "1",
"combo_id": null,
"product_name": "Digital Only",
"total": "2134",
"added": "5",
"canceled": "1",
"terms": [
{
"item_id": "2",
"product_id": "1",
"combo_id": null,
"product_name": "Digital Only",
"item_name": "Annual",
"item_number": "v5yyu",
"total": "73",
"added": 1,
"canceled": 0
},
{
"item_id": "1",
"product_id": "1",
"combo_id": null,
"product_name": "Digital Only",
"item_name": "Monthly",
"item_number": "105lu",
"total": "2061",
"added": 4,
"canceled": 1
}
]
},
{
"product_id": "2",
"combo_id": null,
"product_name": "Digital + Print",
"total": "61",
"added": "4",
"canceled": "0",
"terms": [
{
"item_id": "4",
"product_id": "2",
"combo_id": null,
"product_name": "Digital + Print",
"item_name": "Annual",
"item_number": "tryfb",
"total": "32",
"added": 2,
"canceled": 0
},
{
"item_id": "3",
"product_id": "2",
"combo_id": null,
"product_name": "Digital + Print",
"item_name": "Monthly",
"item_number": "qwdo4",
"total": "29",
"added": 2,
"canceled": 0
}
]
}
]
}
The response includes:
- Total current subscribers
- Subscribers added during the date range
- Subscribers canceled during the date range
- Breakdown of subscribers by plan term