Integration requirements
Authorized User JWT
The User Authorization service needs to generate a JWT token. It must be signed with a shared secret
using HMAC SHA256 alogorithm. The secret
must match JWT secret token available at Settings
> General
for the corresponding accesstype account. The payload of the JWT must consist of email
and id
as shown below:
{
email: "john@example.com", // Email of the user, required
id: 42, // unique id of the user in the external system, required
provider: "quintype", // name of the external system, can be `quintype` or `wordpress`, optional, defaults to quintype
name: "John" // name of the user, optional
}
For a user thats logged in to your website, this JWT token must be set as user context
if you are using Accesstype-JS or passed as a query param if you are using APIs directly.
Story Attributes Endpoint
The Publisher must create a Story Attributes API that responds with attributes of a story.
- It must be a public endpoint.
- It must accept
story-id
query param. - It must respond in the below format
{ visibility: 'subscription', // Can be one of 'subscription', 'login', 'public' //Required published-at: 1571716286097, // Integer //Optional - if not provided defaults to epoch of 1990 access-level: 999, //whole numbers //Optional - if not provided defaults to 0 attributes: [{ // Optional, required if Content Taxonomy Endpoint as described below is used name: 'section', values: ['sports', 'cricket'] },{ name: 'author', values: ['menaka'] },...] }
This endpoint URL needs to be updated as Story attributes Endpoint
in Accesstype at Settings
> General
. Accesstype will be calling this endpoint with a story-id
query string param. The response will be used for next 3 mins
before calling publisher’s server again.
Content Taxonomy Endpoint - Optional
When publisher wants to have fine grain access control based on custom attributes specific to her publishing platform, she must create a Content Taxonomy Endpoint.
- It must be a public endpoint.
- It must respond with custom attributes and their possible values in the below format
[{ type: story, //Optional, defaults to `story` attributes: [{ // Any thing in below format, except the reserved ones i.e ['visibility', 'published-at', 'access-level'] // Max 10 distinct attributes allowed name: 'section', //string values: [{label: 'Sports', value: 'sports'}, {label: 'Science and Tech', value: 'science'}] //array of objects search-url: 'https://pub.com/api/taxonomy/section', //url //optional },{ name: 'author', values: [{label: 'Menaka', value: 'menaka'}, {label: 'John', value: 'john'}] },...] }]
- Each attribute must have
name
andvalues
. values
is an array of objects withlabel
andvalue
fields.label
must be user friendly/readable.value
must be unique, generally its the slug.search-url
can also be passed optionally if the count of values is too large. Everysearch-url
endpoint must acceptq
andlimit
query params and respond in the below format:{ name: 'section', //string values: [{ label: 'Sports', //string value: 'sports' //string }, { label: 'Science and Tech', value: 'science' }] }
-
This endpoint URL needs to be updated in Accesstype Settings. Accesstype would let you configure subscription plans with your custom attributes.
Reader ID - Optional
When publisher wants to avail Metered Paywall feature for Anonymous/Logged-In users, a Reader Id
for every unique user/device needs to be provided to Accesstype.
On mobile apps, device Id can serve as a unique Reader Id
.
Setting a cookie on users browser is the method generally used to identify unique user/device. With more and more tracking prevention policies being adopted by browsers, its the best to set this cookie from 1st party domain. ATJS looks for the availablility of at-meter
cookie for using as Reader Id
. If this is unavailable, it make a POST call to the configured readerIdUrl publisher endpoint.
Below is sample Javascript code that can be used on publisher server for defining the endpoint:
function setReaderId({ request }) {
const cookies = cookie.parse(request.headers.get("Cookie") || "");
let headers = {};
let origin = new URL(request.headers.get("Origin"));
if (!cookies["at-meter"]) {
headers["Set-Cookie"] = `at-meter=${crypto.randomBytes(16).toString("hex")}; Path=/; Domain=${
origin.host
}; Expires=Wed, 21 Oct 2075 07:28:00 GMT; SameSite=None; Secure;`;
}
return new Response("{}", { status: 201, headers: headers });
}