Skip to content

API 20131021

Robert Kulagowski edited this page Jan 23, 2015 · 16 revisions

2015-01-23

This API has been deprecated. Please see https://github.com/SchedulesDirect/JSON-Service/wiki

for the current version.

Notes

Any user with a valid Schedules Direct login may use the API. Developers may send email to grabber@schedulesdirect.org for assistance, but the Developers Corner should be your first stop.

This page describes API version 20131021.

In this document, references to "baseurl" mean "https://json.schedulesdirect.org/20131021/"

The server implements a RESTful interface.

There are multiple tools which can assist if you're implementing a REST client; two good ones are the Postman helper in Chrome and JSONlint at http://jsonlint.org

You can also use the mfdb-json PHP scripts at https://github.com/SchedulesDirect/mfdb-json as a starting point.

DateTime responses are in "Z" / UTC time. There are no Daylight Saving Time adjustments made in any DateTime values.

Headend vs. Lineup

A headend may contain multiple lineups, and a lineup is a specific mapping of channels and stationIDs.

You may have an analog lineup, meaning the channels that you can tune using an analog tuner. In a cable lineup, this would be channels "2" through "125". In the data, these are typically called "DEFAULT".

You may have a digital lineup; one that requires an external set-top-box. For a cable lineup, most digital lineups are designated with an "X" as the device for historical reasons.

You may have a QAM lineup; cable TV content which is available with a QAM tuner. The device type would be "QAM".

Available commands and examples

The following examples give some pointers on how to use the Chrome POSTMan client to step through the tasks that your program must perform in order to use the service.

Obtain a token.

This is the first thing your client must do; almost all commands require a token in the header.

POST https://json.schedulesdirect.org/20131021/token

with the body (click the "Raw" button) of the POST being:

{"username":"rkulagow@rocketmail.com", "password":"sha1hexpassword"}

The password field is the sha1_hex hash of the user's password, resulting in a 40-character string being passed to the server. The hash must be sent in lowercase.

Response:

The server will respond with one of the following:

{
    "code": 0,
    "message": "OK",
    "serverID": "AWS-SD-web.1",
    "token": "f3fca79989cafe7dead71beefedc812b"
}

TODO: include error responses.

The "token" must be passed to the server as part of the header for all requests.

In the following examples, where you see Token: Required you must send the token in the header. In POSTman, click "Headers". Set the Header field to "token" (no quotes, lowercase) and the Value field to the token that you retrieved.

Get status

GET https://json.schedulesdirect.org/20131021/status

Token: Required

Response:

{
    "account": {
        "expires": "2014-06-28T05:16:29Z",
        "messages": [],
        "maxLineups": 16,
        "nextSuggestedConnectTime": "2014-05-20T16:32:12Z"
    },
    "lineups": [
        {
            "ID": "USA-OTA-60030",
            "modified": "2014-05-17T15:47:42Z",
            "uri": "/20131021/lineups/USA-OTA-60030"
        },
        {
            "ID": "USA-OTA-60654",
            "modified": "2014-05-15T17:41:11Z",
            "uri": "/20131021/lineups/USA-OTA-60654"
        },
        {
            "ID": "USA-PA37765-QAM",
            "modified": "2014-05-06T14:50:02Z",
            "uri": "/20131021/lineups/USA-PA37765-QAM"
        }
    ],
    "lastDataUpdate": "2014-05-19T14:44:34Z",
    "notifications": [],
    "systemStatus": [
        {
            "date": "2012-12-17T16:24:47Z",
            "status": "Online",
            "details": "All servers running normally."
        }
    ],
    "serverID": "AWS-SD-web.1",
    "code": 0
}

###Obtain the list of headends in a postal code

GET https://json.schedulesdirect.org/20131021/headends?country=USA&postalcode=60030

Token: Required

Response:

{
    "60030": {
        "type": "Over-the-Air",
        "location": "60030",
        "lineups": [
            {
                "name": "Antenna",
                "uri": "/20131021/lineups/USA-OTA-60030"
            }
        ]
    },
    "4DTV": {
        "type": "Satellite",
        "location": "USA",
        "lineups": [
            {
                "name": "4DTV",
                "uri": "/20131021/lineups/USA-4DTV-DEFAULT"
            }
        ]
    },
    "AFN": {
        "type": "Satellite",
        "location": "USA",
        "lineups": [
            {
                "name": "AFN Satellite",
                "uri": "/20131021/lineups/USA-AFN-DEFAULT"
            }
        ]
    },
    "C-BAND": {
        "type": "Satellite",
        "location": "USA",
        "lineups": [
            {
                "name": "C-Band",
                "uri": "/20131021/lineup/USA-C-BAND-DEFAULT"
            }
        ]
    },
    "DISH602": {
        "type": "Satellite",
        "location": "Chicago",
        "lineups": [
            {
                "name": "DISH Chicago",
                "uri": "/20131021/lineups/USA-DISH602-DEFAULT"
            }
        ]
    },
    "DITV": {
        "type": "Satellite",
        "location": "USA",
        "lineups": [
            {
                "name": "DIRECTV",
                "uri": "/20131021/lineups/USA-DITV-DEFAULT"
            }
        ]
    },
    "DITV602": {
        "type": "Satellite",
        "location": "Chicago",
        "lineups": [
            {
                "name": "DIRECTV Chicago",
                "uri": "/20131021/lineups/USA-DITV602-DEFAULT"
            }
        ]
    },
    "ECHOST": {
        "type": "Satellite",
        "location": "USA",
        "lineups": [
            {
                "name": "DISH Network",
                "uri": "/20131021/lineups/USA-ECHOST-DEFAULT"
            }
        ]
    },
    "GLOBCST": {
        "type": "Satellite",
        "location": "USA",
        "lineups": [
            {
                "name": "Globecast World TV",
                "uri": "/20131021/lineups/USA-GLOBCST-DEFAULT"
            }
        ]
    },
    "GLRYSTR": {
        "type": "Satellite",
        "location": "USA",
        "lineups": [
            {
                "name": "GLRYSTR",
                "uri": "/20131021/lineups/USA-GLRYSTR-DEFAULT"
            }
        ]
    },
    "IL57303": {
        "type": "Cable",
        "location": "Lake Forest",
        "lineups": [
            {
                "name": "Comcast Waukegan/Lake Forest Area - Digital",
                "uri": "/20131021/lineups/USA-IL57303-X"
            }
        ]
    },
    "IL61078": {
        "type": "Cable",
        "location": "Grayslake",
        "lineups": [
            {
                "name": "Saddlebrook Farms - Cable",
                "uri": "/20131021/lineups/USA-IL61078-DEFAULT"
            }
        ]
    },
    "IL63063": {
        "type": "Cable",
        "location": "Mchenry",
        "lineups": [
            {
                "name": "Comcast McHenry & Fox Areas - Digital",
                "uri": "/20131021/lineups/USA-IL63063-X"
            }
        ]
    },
    "IL63463": {
        "type": "Cable",
        "location": "Carpentersville",
        "lineups": [
            {
                "name": "Comcast Algonquin/Elgin Areas - Digital",
                "uri": "/20131021/lineups/USA-IL63463-X"
            }
        ]
    },
    "IL67050": {
        "type": "Cable",
        "location": "Chicago",
        "lineups": [
            {
                "name": "AT&T U-verse TV - Digital",
                "uri": "/20131021/lineups/USA-IL67050-X"
            }
        ]
    },
    "RELAYTV": {
        "type": "Satellite",
        "location": "USA",
        "lineups": [
            {
                "name": "RELAYTV",
                "uri": "/20131021/lineups/USA-RELAYTV-DEFAULT"
            }
        ]
    }
}

Add a lineup to a user's Schedules Direct account

Add a lineup to a user's account. Use the lineup names obtained from the GET /headends that are appropriate for your postal code.

Token: Required

The command follows this format:

PUT /lineups/{COUNTRY}-{LINEUP}-{DEVICE}

So, to add IL57303:X in the United States:

PUT https://json.schedulesdirect.org/20131021/lineups/USA-IL57303-X

Response:

{
    "response": "OK",
    "code": 0,
    "serverID": "AWS-SD-web.1",
    "message": "Added lineup.",
    "changesRemaining": 254,
    "datetime": "2014-05-19T20:16:01Z"
}

###List the lineups a user has added to their account.

Token: Required

GET https://json.schedulesdirect.org/20131021/lineups

Response:

{
    "serverID": "AWS-SD-web.1",
    "datetime": "2014-05-19T20:14:23Z",
    "lineups": [
        {
            "name": "Local",
            "type": "Antenna",
            "location": "60030",
            "uri": "/20131021/lineups/USA-OTA-60030"
        },
        {
            "name": "Local",
            "type": "Antenna",
            "location": "60654",
            "uri": "/20131021/lineups/USA-OTA-60654"
        },
        {
            "name": "Local",
            "type": "QAM",
            "location": "60654",
            "uri": "/20131021/lineups/USA-PA37765-QAM"
        }
    ]
}

Delete a lineup from a user's account.

Token: Required

DELETE /lineups/{COUNTRY}-{LINEUP}-{DEVICE}

Example:

DELETE https://json.schedulesdirect.org/20131021/lineups/USA-IL57303-X

Response:

{
    "response": "OK",
    "code": 0,
    "serverID": "AWS-SD-web.1",
    "message": "Deleted lineup.",
    "changesRemaining": "254",
    "datetime": "2014-05-19T20:18:20Z"
}

StationID / channel mapping for a lineup

Token: Required

GET /lineups/{COUNTRY}-{LINEUP}-{DEVICE}

Example:

GET https://json.schedulesdirect.org/20131021/lineups/USA-IL57303-X

Response:

{
    "map": [
        {
            "stationID": "74348",
            "channel": "001"
        },
        {
            "stationID": "11299",
            "channel": "002"
        },
        {
            "stationID": "12475",
            "channel": "003"
        },
        {
            "stationID": "11848",
            "channel": "004"
        },
        {
            "stationID": "11670",
            "channel": "005"
        },
        {
            "stationID": "11461",
            "channel": "006"
        },
        {
            "stationID": "11653",
            "channel": "007"
        },

etc.

Download program information

POST https://json.schedulesdirect.org/20131021/programs

Token: Required

The body of the request will have the programIDs you are requesting.

{"request":["SH015157750000", "EP000042172058"]}

The response will look like:

{"programID":"SH015157750000","titles":{"title120":"Help in Daily Living"},"eventDetails":{"subType":"Series"},"originalAirDate":"2012-01-01","genres":["Religious"],"showType":"Series","md5":"d7CrQrtdSALdksAr9YDaHQ"}
{"programID":"EP000042172058","titles":{"title120":"The Bold and the Beautiful"},"eventDetails":{"subType":"Series"},"originalAirDate":"2014-05-28","genres":["Soap"],"images":[{"uri":"https:\/\/s3.amazonaws.com\/schedulesdirect-API20131021\/assets\/p183907_b_v5_ac.jpg","dimension":"w=240px|h=360px","md5":"2a46b9984f91bc5531136c"}],"cast":[{"personId":"33184","nameId":"33184","name":"John McCook","role":"Actor","billingOrder":"01"},{"personId":"60861","nameId":"60861","name":"Susan Flannery","role":"Actor","billingOrder":"02"},{"personId":"56539","nameId":"56539","name":"Ronn Moss","role":"Actor","billingOrder":"03"},{"personId":"35962","nameId":"35962","name":"Katherine Kelly Lang","role":"Actor","billingOrder":"04"},{"personId":"1859","nameId":"1859","name":"Jack Wagner","role":"Actor","billingOrder":"05"},{"personId":"314870","nameId":"322751","name":"Texas Battle","role":"Actor","billingOrder":"06"},{"personId":"258308","nameId":"261872","name":"Brandon Beemer","role":"Actor","billingOrder":"07"},{"personId":"199845","nameId":"683742","name":"Sarah Joy Brown","role":"Actor","billingOrder":"08"},{"personId":"314743","nameId":"322612","name":"Scott Clifton","role":"Actor","billingOrder":"09"},{"personId":"581436","nameId":"606454","name":"Zack Conroy","role":"Actor","billingOrder":"10"},{"personId":"86347","nameId":"86347","name":"Don Diamont","role":"Actor","billingOrder":"11"},{"personId":"38997","nameId":"38997","name":"Lesley-Anne Down","role":"Actor","billingOrder":"12"},{"personId":"467","nameId":"467","name":"Patrick Duffy","role":"Actor","billingOrder":"13"},{"personId":"201420","nameId":"203327","name":"Adrienne Frantz","role":"Actor","billingOrder":"14"},{"personId":"207731","nameId":"209765","name":"Jennifer Gareis","role":"Actor","billingOrder":"15"},{"personId":"154046","nameId":"158401","name":"Rick Hearst","role":"Actor","billingOrder":"16"},{"personId":"209275","nameId":"211473","name":"Ashley Jones","role":"Actor","billingOrder":"17"},{"personId":"219518","nameId":"221932","name":"Kyle Lowder","role":"Actor","billingOrder":"18"},{"personId":"520723","nameId":"539170","name":"Jacqueline MacInnes Wood","role":"Actor","billingOrder":"19"},{"personId":"513765","nameId":"529540","name":"Kimberly Matula","role":"Actor","billingOrder":"20"},{"personId":"78173","nameId":"78173","name":"Alley Mills","role":"Actor","billingOrder":"21"},{"personId":"26015","nameId":"26015","name":"Heather Tom","role":"Actor","billingOrder":"22"},{"personId":"67534","nameId":"67534","name":"Hunter Tylo","role":"Actor","billingOrder":"23"},{"personId":"160503","nameId":"161114","name":"Courtnee Draper","role":"Actor","billingOrder":"24"},{"personId":"158217","nameId":"158546","name":"Schae Harrison","role":"Actor","billingOrder":"25"},{"personId":"657589","nameId":"683757","name":"Adam Gregory","role":"Actor","billingOrder":"26"},{"personId":"605072","nameId":"627584","name":"Kristolyn Lloyd","role":"Actor","billingOrder":"27"},{"personId":"1106","nameId":"1106","name":"A Martinez","role":"Actor","billingOrder":"28"},{"personId":"67625","nameId":"67625","name":"Andrea Evans","role":"Actor","billingOrder":"29"},{"personId":"152236","nameId":"152366","name":"Sean Whalen","role":"Actor","billingOrder":"30"},{"personId":"521001","nameId":"539609","name":"Lawrence Saint-Victor","role":"Actor","billingOrder":"31"},{"personId":"67555","nameId":"67555","name":"Thorsten Kaye","role":"Actor","billingOrder":"32"}],"crew":[{"personId":"264987","nameId":"268563","name":"Bradley Bell","role":"Producer","billingOrder":"01"}],"showType":"Series","md5":"bOt\/jJr0iAJSQY8WTyy4FA"}

Each line is a separate JSON object. Taking the first response and feeding it into jsonlint.com:

{
    "programID": "SH015157750000",
    "titles": {
        "title120": "Help in Daily Living"
    },
    "eventDetails": {
        "subType": "Series"
    },
    "originalAirDate": "2012-01-01",
    "genres": [
        "Religious"
    ],
    "showType": "Series",
    "md5": "d7CrQrtdSALdksAr9YDaHQ"
}

###Download the schedules for stationIDs

POST https://json.schedulesdirect.org/20131021/schedules

Token: Required

The body of the request will have the stationIDs that you are requesting schedules for.

{"request":[10002, 20454]}

Will return something which looks like this:

{"stationID":"10002","programs":[{"programID":"SH003712850000","md5":"LiAma3Y25JBWkrJvbNDvTg","airDateTime":"2014-05-02T00:00:00Z","duration":3600},{"programID":"SH006701200000","md5":"WI1BR8w4nPmXOVwe\/qK2xA","airDateTime":"2014-05-02T01:00:00Z","duration":7200,"liveTapeDelay":"Live","new":true},{"programID":"SH012546070000","md5":"vQ7tHUkfCvzyLY2OoG6rrQ","airDateTime":"2014-05-02T03:00:00Z","duration":3600},{"programID":"SH006701200000","md5":"WI1BR8w4nPmXOVwe\/qK2xA","airDateTime":"2014-05-02T04:00:00Z","duration":3600},{"programID":"SH017588780000","md5":"98wfRh+5cV741AFgFZlm6A","airDateTime":"2014-05-02T05:00:00Z","duration":3600},{"programID":"SH006701200000","md5":"WI1BR8w4nPmXOVwe\/qK2xA","airDateTime":"2014-05-02T06:00:00Z","duration":7200,"liveTapeDelay":"Live","new":true},{"programID":"SH005532720000","md5":"O2f14xmm2a9FB6VWvO7q8w","airDateTime":"2014-05-
02T08:00:00Z","duration":3600}
{"programID":"SH000006800000","md5":"XFG2oYyaxHLeGFnIYADtNA","airDateTime":"2014-05-04T00:00:00Z","duration":1800,"audioProperties":["cc","stereo"]}}
{"stationID":"20454","programs":[{"programID":"EP009311820166","md5":"dA+SfzzL0H7wwiw9ZIux1w","airDateTime":"2014-05-02T00:00:00Z","duration":1860,"contentRating":[{"body":"USA Parental Rating","code":"TVPG"}],"contentAdvisory":{"USA Parental Rating":["Language","Dialog"]},"syndication":{"source":"CBS","type":"Broadcast Network"},"new":true,"audioProperties":["cc","stereo","DD 5.1"],"videoProperties":["hdtv"]},{"programID":"EP017398410024","md5":"DWgiUeVMH10G1Uj+Pukj\/A","airDateTime":"2014-05-02T00:31:00Z","duration":1800,"contentRating":[{"body":"USA Parental Rating","code":"TVPG"}],"contentAdvisory":{"USA Parental Rating":["Language","Dialog"]},"syndication":{"source":"CBS","type":"Broadcast Network"},"new":true,"audioProperties":["cc","stereo","DD 5.1"],"videoProperties":["hdtv"]}

(etc)

"programs" is an array of many elements; parsing the JSON will allow your program to

  • Check whether it needs to download the program details because it has never downloaded this program before (you don't already have a copy of the programID in your local cache)
  • The md5 of the program has changed, so it should be re-downloaded to get updated information.

###Delete a system message

DELETE /messages/{messageID} Deletes non-system status messages from the status response.

###Download graphics, channel logos, banners

GET /assets/{uri}

Images, fanart, logos, etc will have a URI in the JSON response. If the URI is complete, it will point to Amazon S3, in which case your application should pull the image directly from Amazon. If the URI is incomplete (no http:// for example), then send the request to Schedules Direct. Your application will then receive a 303 redirect.

#Tasks your client must perform

A client process flow during initial configuration would be:

  • Using a web browser, configure an account at the Schedules Direct website. Accept the Terms of Service, etc.

Using a grabber client:

  • Obtain the token for this session.
  • Obtain the current status.
  • If the system status is "OFFLINE" then disconnect; all further processing will be rejected at the server. A client should not attempt to reconnect for 1 hour.
  • Obtain the list of headends for the postal code.
  • Allow the user to select which headends they want data for. Use the PUT function to add that headend to their account at Schedules Direct. By default, a user may have 4 headends in their account, but this can be modified by sending a request through the Schedules Direct ticket service or by sending an email to grabber@schedulesdirect.com
  • You may perform 6 "adds" in a 24 hour period. The status response will indicate the number of lineup changes remaining.
  • Download the lineups for the headends. This will provide the user the mapping of channels, callsigns and station IDs.
  • Allow the user to select which stations they wish to receive data for - this is done at the client; the server does not maintain a list of stations for the user, only the lineup name.
  • Send a request for the schedules for those stationID's to the server.
  • Process the schedules; each schedule for each station id will contain at least 12 days of data.
  • Determine which program id's need to be downloaded. During an initial download, the client will have an empty cache of program id's / MD5 hashes, so the client will need to download all relevant program id's.

NOTE: the server has been successfully tested with over 30,000 program ID requests, but the response may overload the client. You are strongly encouraged to chunk your requests to prevent your client from running out of memory. In addition, there is a 10 minute timeout on the server side. Requesting 30,000 program IDs over a 33.6Kbps modem will result in a failed download. You must ensure that the number of programs requested can be serviced within 10 minutes.

Once the client is in a steady state:

  • Obtain a token.
  • Obtain the current status.
  • If the system status is "OFFLINE" then disconnect; all further processing will be rejected at the server. A client should not attempt to reconnect for 1 hour.
  • Check the status object and determine if any headends on the server have newer "modified" dates than the one that is on the client. If yes, download the updated lineup for that headend.
  • If there are no changes to the headends, check the last data update in the status object. If the last data update on the server is the same as what the user has saved, then there are no updated schedules, and the client should disconnect.
  • If the last update data is newer, then download the schedules for the station id's that the user has selected.
  • Honor the nextScheduled time in the status object; if your client connects during server-side data processing, the nextScheduled time will be "closer", however reconnecting while server-side data is being processed will not result in newer data.
  • Parse the schedule, determine if the MD5 of the program for a particular timeslot has changed. If the program ID for a timeslot is the same, but the MD5 has changed, this means that some sort of metadata for that program has been updated.
  • Request the "delta" program id's as determined through the MD5 values.

Requesting only station id's and program id's that the user is interested in will minimize the time and data required in each download.

Data updates occur six days a week, Monday through Saturday and are usually complete by 10:00 Central Standard Time.

Error Codes:

The system may respond to a request and send back an error code.

<style type="text/css"> .tg-left { text-align: left; } .tg-right { text-align: right; } .tg-center { text-align: center; } .tg-bf { font-weight: bold; } .tg-it { font-style: italic; } .tg-table-plain { border-collapse: collapse; border-spacing: 0; font-size: 100%; font: inherit; } .tg-table-plain td { border: 1px #555 solid; padding: 10px; vertical-align: top; } </style>
Response Internal Code Error
OK 0
INVALID_JSON 1001 JSON decode error
API_VERSION_MISSING 1002 No API sent
INVALID_API_VERSION 1003 Wrong API
HASH_MISSING 1004 randhash wasn't sent
UNSUPPORTED_COMMAND 2000 Unsupported action
REQUIRED_ACTION_MISSING 2001 No action
REQUIRED_OBJECT_MISSING 2002 No object
REQUIRED_PARAMETER_INVALID 2003 Returned error text will contain specific information
DUPLICATE_HEADEND 2100 Adding a headend which is already in account
INVALID_HEADEND 2101 Requested a headend which isn't in the system
INVALID_HEADEND_DELETE 2102 Deleting a headend not in account
SERVICE_OFFLINE 3000 Service offline for maintenance
ACCOUNT_EXPIRED 4001 Account Expired
INVALID_HASH 4002 Wrong hash
INVALID_USER 4003 User account doesn't exist
ACCOUNT_LOCKOUT 4004 Too many failed attempts to login
MAX_HEADEND_CHANGES_REACHED 4100 Max changes for lineup
MAX_HEADENDS 4101 Max headends in account reached
NO_HEADENDS 4102 User doesn't have headends in account
HCF 9999 Unknown error