Skip to content

Authorship Intake

gabep-tech edited this page May 11, 2026 · 7 revisions

The Authorship endpoint lets API clients submit and retrieve Authorship intake data for reseller-owned accounts and campaigns.

This endpoint is used when a campaign has an Authorship workflow task and the reseller needs to provide author profile information, LinkedIn details, optional biography content, and an optional author image.

All requests require API authorization using the same Bearer JWT and/or API key authentication used by other Semify v1 API endpoints.

Base Endpoint

/api/v1/authorship

Available Methods

Method Path Purpose
POST /api/v1/authorship Create Authorship intake data
GET /api/v1/authorship List Scheduled Authorship tasks

POST /api/v1/authorship

Creates a new Authorship intake record for a reseller-owned account and campaign.

When successful, this endpoint:

  • Verifies the authenticated reseller owns the account.
  • Verifies the reseller owns the campaign.
  • Confirms an Authorship task exists for the campaign.
  • Requires the Authorship task to be in Scheduled status.
  • Prevents duplicate intake records for the same account and campaign.
  • Inserts a row into authorship_intake.
  • Inserts related content rows into authorship_intake_content.
  • Updates the task link_image when a valid image URL is supplied.
  • Adds a task note containing the submitted intake details.
  • Optionally creates a LinkedIn entry in the campaign password locker.

Required Request Body

{
  "account": {
    "account_id": 12345,
    "camp_id": 54321
  },
  "author": {
    "full_name": "Jane Doe",
    "position": "Editor",
    "business_name": "Example Co"
  },
  "linked_in": {
    "url": "https://www.linkedin.com/in/janedoe"
  }
}

Required Fields

Field Type Description
account.account_id integer Account ID for the intake
account.camp_id integer Campaign ID for the intake
author.full_name string Author’s full name
author.position string Author’s title or position
author.business_name string Business name associated with the author
linked_in object LinkedIn information object

Optional Fields

Field Type Description
linked_in.url string Public LinkedIn profile URL
linked_in.username string LinkedIn username for password locker storage
linked_in.password string LinkedIn password, stored encrypted
link_image string Author image URL
experience_history string Author experience/history
interests_facts string Interests or notable facts
areas_expertise string Areas of expertise
education string Education details
current_work string Current work details
credentials string Credentials or certifications
pub_awards string Publications or awards

LinkedIn Handling

The linked_in object is required, but its child fields are optional.

If only linked_in.url is supplied, the API stores the URL on the intake and may create a LinkedIn password locker entry with the URL in the note field.

If both linked_in.username and linked_in.password are supplied, the password is encrypted before storage and saved for internal password locker workflows.

Always submit LinkedIn credentials over HTTPS.

Image Handling

If link_image is supplied, the API normalizes and validates it.

If the URL does not start with http:// or https://, the API prepends https://.

The image URL is only kept if it contains one of the following extensions:

  • .png
  • .gif
  • .jpg
  • .jpeg
  • .bmp

If the image URL does not contain one of those extensions, the value is cleared.

Example POST Request

curl -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "account": {
      "account_id": 12345,
      "camp_id": 54321
    },
    "author": {
      "full_name": "Jane Doe",
      "position": "Editor",
      "business_name": "Example Co"
    },
    "linked_in": {
      "url": "https://www.linkedin.com/in/janedoe"
    },
    "link_image": "https://example.com/photo.jpg",
    "credentials": "Certified Example",
    "experience_history": "10 years in SEO"
  }' \
  "https://uat.services.semify.com/api/v1/authorship"

Example POST Request With LinkedIn Credentials

curl -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "account": {
      "account_id": 12345,
      "camp_id": 54321
    },
    "author": {
      "full_name": "Jane Doe",
      "position": "Editor",
      "business_name": "Example Co"
    },
    "linked_in": {
      "url": "https://www.linkedin.com/in/janedoe",
      "username": "user@example.com",
      "password": "useStrongSecretsOnlyOnHTTPS"
    }
  }' \
  "https://uat.services.semify.com/api/v1/authorship"

Successful POST Response

{
  "data": {},
  "error": false,
  "messages": [
    "Authorship created successfully",
    "Success"
  ]
}

Common POST Errors

Duplicate Intake

Returned when an intake already exists for the same account and campaign.

{
  "data": {},
  "error": true,
  "messages": [
    "An intake already exists for this account and campaign. - errorcode: authorship-v1-create:2",
    "Bad Request"
  ]
}

Account Not Owned By Reseller

{
  "data": {},
  "error": true,
  "messages": [
    "The reseller does not own this account. - errorcode: authorship-v1-create:2",
    "Bad Request"
  ]
}

Campaign Not Owned By Reseller

{
  "data": {},
  "error": true,
  "messages": [
    "The reseller does not own this campaign. - errorcode: authorship-v1-create:3",
    "Bad Request"
  ]
}

Missing Authorship Plan Or Task

{
  "data": {},
  "error": true,
  "messages": [
    "Account does not have Authorship plans - errorcode: authorship-v1-create:4",
    "Bad Request"
  ]
}

Task Not Scheduled

{
  "data": {},
  "error": true,
  "messages": [
    "Task must be in Scheduled status (status_id = 1) to submit an intake. Current status: 2 - errorcode: authorship-v1-create:3",
    "Bad Request"
  ]
}

GET /api/v1/authorship

Returns Scheduled Authorship tasks for the authenticated reseller.

The endpoint only returns tasks that match the Authorship task type and are not completed.

Authorship task rules:

  • task_type_id = 136
  • status_id = 1
  • date_completed IS NULL
  • Campaign must belong to the authenticated reseller

Query Parameters

Parameter Type Required Description
account_id integer No Filter by account ID
camp_id integer No Filter by campaign ID
start_date date No Filter by task due date greater than or equal to this date
end_date date No Filter by task due date less than or equal to this date
needsIntakeData boolean No true returns tasks without intake data; false returns tasks with intake data

Dates should use YYYY-MM-DD format.

Example GET Request

curl -H "Authorization: Bearer $TOKEN" \
  "https://uat.services.semify.com/api/v1/authorship?account_id=12345&needsIntakeData=true"

Successful GET Response

{
  "data": [
    {
      "task_id": 1001,
      "camp_id": 54321,
      "task_name": "Content - Website Authorship Page",
      "task_type_id": 136,
      "task_type_name": "Authorship",
      "camp_name": "Example Campaign",
      "account_id": 12345,
      "status": "Scheduled",
      "date_due": "2026-05-15",
      "created_date": "2026-05-01",
      "intake_id": null
    }
  ],
  "error": false,
  "messages": [
    "Successfully retrieved 1 scheduled Authorship tasks",
    "with filters: account_id: 12345, needsIntakeData: true"
  ]
}

GET Response Fields

Field Description
task_id Task ID
camp_id Campaign ID
task_name Task name
task_type_id Task type ID, expected to be 136
task_type_name Display name for the task type
camp_name Campaign name
account_id Account ID
status Task status
date_due Task due date
created_date Task creation date
intake_id Authorship intake ID, or null if intake data has not been submitted

GET Validation Error

Invalid dates, invalid date ranges, or invalid needsIntakeData values may return a validation error.

{
  "data": {},
  "error": true,
  "messages": [
    "start_date must be in YYYY-MM-DD format; needsIntakeData must be either 'true' or 'false'"
  ]
}

GET No Results

{
  "data": {},
  "error": true,
  "messages": [
    "No authorship tasks found"
  ]
}

Typical Workflow

  1. Use GET /api/v1/authorship?needsIntakeData=true to find Scheduled Authorship tasks that still need intake data.
  2. Select the desired account_id and camp_id from the returned task.
  3. Submit POST /api/v1/authorship with the author profile, LinkedIn object, and optional content fields.
  4. Use GET /api/v1/authorship?account_id={account_id}&camp_id={camp_id}&needsIntakeData=false to confirm the intake is attached.

Important Notes

  • Only one intake can exist per account_id and camp_id.
  • The Authorship task must be Scheduled before intake data can be submitted.
  • start_date and end_date filter against task due date, not task creation date.
  • LinkedIn passwords are encrypted before storage.
  • Do not submit LinkedIn credentials over non-HTTPS connections.
  • link_image must point to a common raster image type or it will be ignored.

Clone this wiki locally