Link2Feed RESTful Client and Appointment API

This space documents the general process for authenticating against and utilizing the Client and Appointment API. This is the core API behind our CNCT tool and allows the following interactions:

  • Creating New Clients and their Households

  • Updating Existing Clients and their Households

  • Booking Appointments for the Future

  • Updating Existing Appointments

  • Cancelling Existing Appointments

Any questions, queries or concerns can be forwarded to our support team by emailing support@link2feed.com and requesting assistance. To sign up to use this API, please contact your account manager.

 

Authentication

All API requests are authenticated using HMAC Signed Requests and an API Key. This is similar to the method that AWS uses for many of its API requests.

Required Credentials

To sign a request, you need the following three pieces of information, provided by Link2Feed:

  • API Key - To be sent as part of HTTP request and direct authorization

  • Secret Key - To be used to sign the HTTP request, but not sent along with the request

  • URL - The endpoint that will receive and process the request

Required HTTP Headers

  • Host

    • Hostname of the targeted endpoint

    • Will change per-environment. eg- example.com

  • Authorization

    • Calculated signature based on the contents of the request

    • Will change per-request. eg- HMAC-SHA256 0fa36b84ab47a14ec56934927105e56d83424ec5bd649680e0d52bbb89e28ed0

  • Signed-Headers

    • Headers signed against, in addition to the request body, that are included in the signature. Note that this is case-sensitive.

    • Exactly: host,signed-headers

  • X-API-Key

    • API Key provided by Link2Feed Staff. eg- 6934927105e56d83424ec5bd64

Signing Process

  1. Gather Required Information:

    1. HTTP Method eg- GET/POST/PUT/PATCH/DELETE

    2. HTTP URL, including query parameters eg- https://example.com/api/v1/demo?id=1234

    3. Request Payload/Body

    4. Request Headers

  2. Combine and Format Data to Be Signed

    1. The data must be “escaped” for safe transit.

    2. The data is to be concatenated. Ordering of the fields need only be internally-consistent, so the data sent must match the order of the fields in the data that is signed.

    3. The package to be signed consists of three parts:

      1. A Request Line: A string consisting of the HTTP Request Line format, notably “The Request-Line begins with a method token, followed by the Request-URI and the protocol version, and ending with CRLF. The elements are separated by SP characters. No CR or LF is allowed except in the final CRLF sequence.” For example: POST /api/v1/clients/find HTTP/1.1\r\n

      2. The Signed Headers: Specifically, these are the Host and Signed-Headers headers, and their contents. Formatted as header-name, followed by a colon and a space, then the value of the header. Each header is followed by a CRLF. For example: host: redacted.link2feed.com\r\nsigned-headers: host,signed-headers\r\n

      3. The Body of the Request: If the request is JSON-formatted (ie- Content-Type is application/json) then this is simply the JSON String. If the request is formatted as form-data, each key/value pair must be a) “escaped” for safe HTTP transfer, b) split into Key and Value, c) represented as Key=Value, and d) the collection must be joined together with ampersands between key/value pairs. For example, if the form-data is firstName: Eleven, lastName: O'Clock, dob: 1980-01-01, then the body to be signed would be: firstName=Eleven&lastName=O%27Clock&dob=1980-01-01 where, notably, the ' in O'clock is escaped to %27.

    4. Combine the three parts into a single string, separated by CRLF characters. For example the above:

      POST /api/v1/clients/find HTTP/1.1\r\nhost: redacted.link2feed.com\r\nsigned-headers: host,signed-headers\r\n\r\nfirstName=Eleven&lastName=O%27Clock&dob=1980-01-01

      Note: As each header ends with a CRLF and then the joining adds another, there are two CRLF character blocks between the headers and the body. The same request as JSON, and with the CRLF characters rendered would be:

      POST /api/v1/clients/find HTTP/1.1 host: redacted.link2feed.com signed-headers: host,signed-headers { "firstName":"Eleven", "lastName":"O'Clock", "dob":"1980-01-01" }
  3. Build the Signature

    1. Once the string is ready to be signed, it must go through two main processes:

      1. Gathering the HMAC SHA-256 hash of the contents, signed with the Secret Key provided by Link2Feed

      2. Converting the resultant hash to Base64

  4. Send the Request

    1. Once the Base64’ed value of the HMAC SHA-256 hash is collected, it is added as an additional “Authorization” header to the request in the form HMAC-SHA256 _______CalculatedHash_______.

    2. The request can then be sent. It must include both the HMAC signature as an Authorization header, and the API-Key as an X-API-Key header. So for example, the above JSON example request (signed against a secret key of 123456789) would produce the following request headers:

      Authorization: "HMAC-SHA256 3deOvVHhL1zyHyS7+cWPsPW+OnhxQXHJzLsR9UyAIQ4="

      Signed-Headers: "host,signed-headers"

      X-API-Key: "6934927105e56d83424ec5bd64"

      Content-Type: "application/json"

      Host: "redacted.link2feed.com"

       

JavaScript Example

The following is built against Postman (https://www.postman.com/) Pre-request Scripts (https://learning.postman.com/docs/writing-scripts/pre-request-scripts/). Working sample Collections for Postman are included at the bottom of this document as Appendix A.

Notable changes to adapt this elsewhere: pm.variables.get() is used to pull Postman’s environment variables out, and are used here to pull the Secret and URL. If adapting this to other uses, replace the SECRET_KEY variable, and adapt the SIGNED_HEADERS constant to refer to the hostname from a given source.

The signed header that would go into an Authorization header can be produced from a call to, for example, getAuthHeader("GET", "https://example.com/api/v1/demo", '{"sample":"data"}', {"X-API-Key": "6934927105e56d83424ec5bd64", "Host": "example.com", "Signed-Headers": "host,signed-headers"})

Notably below, some shortcuts are taken using the Postman objects. Specifically:

  • request['data'] is a Postman RequestBody object, which is effectively in the context of this sample an Object or Key/Value store (ie- A form/json data element named foo is accessed as request['data']['foo']).

  • request['headers'] is a Postman HeaderList object, which is effectively in the context of this sample an Object or Key/Value store (ie- The host header is accessed as request['headers']['host']).

var SECRET_KEY = pm.variables.get("SECRET"); var SIGNED_HEADERS = [ ["host", pm.variables.get("API_URL")] ]; var SIGNED_HEADER = "signed-headers: host,signed-headers\r\n"; function getPath(url) { var pathRegex = /.+?\:\/\/.+?(\/.+?)(?:#|\?|$)/; var result = url.match(pathRegex); return result && result.length > 1 ? result[1] : ''; } function getQueryString(url) { var arrSplit = url.split('?'); if(arrSplit.length == 1) return ''; var params = arrSplit[1].split('&'); params.sort(); return '?'+params.join('&'); } function getAuthHeader(httpMethod, requestUrl, requestBody, requestHeaders) { if (httpMethod == 'GET' || !requestBody) { requestBody = ""; } else { if(requestHeaders != null && requestHeaders["content-type"] != "application/json") { var output = ""; Object.keys(requestBody).forEach(function(e) { output += escape(e) + "=" + escape(requestBody[e]) + "&"; }); requestBody = output.substring(0, output.length -1); // Remove the last & } } var requestLine = httpMethod +" "+getPath(requestUrl)+getQueryString(requestUrl)+" HTTP/1.1"; var headers = ""; for(var i = 0; i < SIGNED_HEADERS.length; ++i) { headers += (SIGNED_HEADERS[i][0] + ': ' + SIGNED_HEADERS[i][1] + '\r\n'); } headers += SIGNED_HEADER; var body = requestBody; var hashedRequestData = [requestLine, headers, body].join('\r\n'); var hmacDigest = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(hashedRequestData, SECRET_KEY)); var authHeader = "HMAC-SHA256 "+hmacDigest; return authHeader; } pm.environment.set("HMAC_AUTH_HEADER", getAuthHeader(request['method'], request['url'], request['data'], request['headers']));

Additional Documentation

  1. AWS Signing and authenticating REST requests: https://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html

  2. ApiAuth - HMAC authentication for Rails and HTTP Clients: https://github.com/mgomes/api_auth

  3. HMAC on Wikipedia: https://en.wikipedia.org/wiki/HMAC

  4. Online HMAC Generator: https://codebeautify.org/hmac-generator

  5. IETF RFC 2104 - HMAC: Keyed-Hashing for Message Authentication: https://tools.ietf.org/html/rfc2104

  6. HMAC Tools for Various Languages

    1. C: https://github.com/ogay/hmac

    2. Java: https://docs.oracle.com/javase/1.5.0/docs/guide/security/jce/JCERefGuide.html#HmacEx

    3. JavaScript/NodeJS: https://nodejs.org/api/crypto.html#crypto_class_hmac

    4. PHP: https://www.php.net/manual/en/function.hash-hmac.php

    5. Python: https://docs.python.org/3/library/hmac.html

    6. Ruby: https://ruby-doc.org/stdlib-2.4.0/libdoc/openssl/rdoc/OpenSSL/HMAC.html

Data Types API

Purpose: This endpoint is used to gather network-specific identifiers and other configuration data. Some of it is very CNCT-specific (eg- customized text blocks for the CNCT UI) but the big value is in the data types that must be passed along as part of the required details configured in the API.

HTTP URL: https://{{ HostName }}/api/v1/datatypes where {{ HostName }} is provided by Link2Feed, and varies depending on the environment (Test, Live, Staging, etc) being accessed.

HTTP Method: GET

Request Headers: Authorization, Host, Signed-Headers, X-API-Key

Request Payload: Nothing

Response Format: JSON Object

Response Fields:

  • Data Types – Many of the fields in Link2Feed are stored with a human-readable label (eg- “Own House”) and a more machine-friendly name (eg- “own_house”). When interacting with people, it is best to use the label. When building requests to create or update client details, the system expects the machine-friendly name instead of the label.

    • maritalStatuses: Network-specific options for the Marital Status question in the client profile, in the form of name/label.

    • genders: Network-specific options for the Gender question in the client profile, in the form of name/label.

    • housingTypes: Network-specific options for the Housing Types question in the client profile, in the form of name/label.

    • ethnicities: Network-specific options for the Ethnicities question in the client profile, in the form of name/label.

    • selfIdentificationTypes: Network-specific options for the Self Identifies As question in the client profile, in the form of name/label.

    • educationTypes: Network-specific options for the Highest Education Level Completed question in the client profile, in the form of name/label.

    • employmentTypes: Network-specific options for the Employment Type question in the client profile, in the form of name/label.

    • income_sourceTypes: Network-specific options for the Income Type question in the client profile, in the form of name/label.

    • relationships: Network-specific options for the Relationship question in the profile of secondary household members, in the form of name/label.

    • socialProgramTypes: Network-specific options for the Social Programs that the client is receiving in the client profile, in the form of name/label.

    • expenseTypes: Network-specific options for the Expense Type question in the client profile, in the form of name/label.

    • referredBy: Network-specific options for the Referred By question in the client profile, in the form of name/label.

    • dietaryConsiderationTypes: Network-specific options for the Dietary Considerations question in the client profile, in the form of name/label.

    • languageTypes: Network-specific options for the Languages question in the client profile, in the form of name/label.

  • Other Configuration Fields

    • states: Network-specific list of States or Provinces where agencies currently have sites within Link2Feed.

    • agencies: A list of Link2Feed agencies that currently have appointment programs available for booking through the API. Each record includes the agency name, its Link2Feed unique ID number, and a listing of its address to share with the client when considering which location to book at.

    • questionPhrasing: A Network-specific list of text bites that have been selected in the CNCT dashboard to provide specific user-friendly prompts for each question.

    • welcomeMessage: Network-specific text block used to represent the very first text on the CNCT landing page.

    • informationDisclaimer: Network-specific text block that is either the network’s current information-sharing consent disclaimer in Link2Feed, or a custom textbox setup in the CNCT dashboard.

    • consentDisclaimer: Network-specific text block that provides a user-friendly prompt for asking the user if they consent to being contacted.

    • householdMessage: Network-specific text block that provides a user-friendly prompt at the top of the Household Members page of CNCT.

    • thankYouMessage: Network-specific text block that provides a user-friendly message at the end of the client intake process of CNCT.

    • imageUrl: A URL that can be set in the CNCT dashboard for an image to display to users in CNCT.

    • foodBankName: The name of the Network that all of these details are drawn from.

    • enabledFields: A network-specific list that can be edited in the CNCT dashboard to select which of the common fields are turned on or off.

    • dateFormat: The date format to display and transfer dates.

    • useAutocomplete: A CNCT configuration flag for whether or not the network uses address autocomplete at all.

    • useUSPSAutocomplete: A CNCT configuration flag for whether or not to use specifically the USPS autocomplete system.

Response Codes:

  • 200 - OK. Response payload includes the data types details.

  • 401 - Unauthorized. There was an issue with the request. Ensure that all required headers are accurate (X-API-Key, Authorization, Signed-Headers and Host).

  • 5XX - Server Error. Any 5XX error (500, 502, 503, 504) means a Link2Feed error has occurred. Please contact Link2Feed if this persists.

Sample Response:

Clients API

Purpose: This collection of endpoints are used to create and update client profiles.

Find a Client by Minimal Details (First Name, Last Name and Date of Birth)

Purpose: This endpoint finds existing clients, or, failing to find an existing client, will return a new session key to begin interacting with the API to build a new client.

HTTP URL: https://{{ HostName }}/api/v1/clients/find where {{ HostName }} is provided by Link2Feed, and varies depending on the environment (Test, Live, Staging, etc) being accessed. Note: the URL Query Parameter skipDupecheck=truecan be appended to this URL (eg- .../clients/find?skipDupecheck=true) in order to skip duplicate checking. This may be desired to avoid potential privacy issues, depending on the access level of the tools utilizing this API.

HTTP Method: POST

Request Headers: Authorization, Content-Type, Host, Signed-Headers, X-API-Key

Request Payload: JSON Object
This object has three fields. If any of them are missing, the request will fail. These represent the client’s first name, last name, and date of birth. With these three identifiers most clients in the system can be uniquely identified.

Response Format: JSON Object

Response Fields:

  • Always-Present Fields

    • clientProfileId: A globally-unique ID (GUID) representing the client sought for. This client may or may not already exist in the Link2Feed system. If the client already exists, the GUID represents their GUID in the database. If the client does not exist, a new GUID will be used to start a client-creation session. This can be triggered to always request a new GUID (ie- to skip the duplicate-checking process) by adding the query parameter skipDupecheck=true to the initial call.

    • filters: This array describes additional filters which may be applied to narrow down potential duplicates. Currently, the only filter available is an address filter, which provides several fake addresses and the real addresses of potential duplicates, masked to hide the address. For example if the client’s address were 1234 Cherry Lane, it would be masked to 1234 C****y L**e. This information can be sent to another endpoint to pick from existing duplicates.

  • Sometimes-Present Fields

    • link2feedId: If the client can be uniquely identified given the request details, the response will include their unique numerical identifier within the Link2Feed system.

Response Codes:

  • 200 - OK. Response payload includes the details requested.

  • 400 - Bad Request. Will respond with a message including details of the request field errors. For example: { "message": "firstName field not supplied." }

  • 401 - Unauthorized. There was an issue with the request. Ensure that all required headers are accurate (X-API-Key, Authorization, Signed-Headers and Host).

  • 5XX - Server Error. Any 5XX error (500, 502, 503, 504) means a Link2Feed error has occurred. Please contact Link2Feed if this persists.

Sample Response for No Client Found:

Sample Response for Found Single Client:

Sample Response for Found Multiple Clients:

 

Find a Client by Filters

Purpose: This endpoint potentially chooses a client from the potential filters. For example, the previous API endpoint could produce 7 address options. If this endpoint receives the correct session ID and address option to match an existing client, it will respond with a valid client option. If one of the invalid options is selected, however, it will respond with a new client session.

HTTP URL: https://{{ HostName }}/api/v1/clients/findbyfilters where {{ HostName }} is provided by Link2Feed, and varies depending on the environment (Test, Live, Staging, etc) being accessed.

HTTP Method: POST

Request Headers: Authorization, Content-Type, Host, Signed-Headers, X-API-Key

Request Payload: JSON Object
This object has two top-level fields. If any of them are missing, the request will fail. These represent the client’s GUID or profile ID, which is also the session key for working with this client, and also the specific filters chosen from previous filters.

Response Format: JSON Object

Response Fields:

  • Always-Present Fields

    • clientProfileId: A globally-unique ID (GUID) representing the client sought for. This client may or may not already exist in the Link2Feed system. If the client already exists, the GUID represents their GUID in the database. If the client does not exist, a new GUID will be used to start a client-creation session. Note: if an existing client is found, the clientProfileId provided by the response will differ from the clientProfileId provided in the request. If they are the same, it means a new client is being created.

  • Sometimes-Present Fields

    • filters: This array describes additional filters which may be applied to narrow down potential duplicates. Currently, the only filter available is an address filter so this will not be seen in practice as this response is only reached by providing an address, however, the system is extensible enough to provide other filtration plans to further sub-divide potential duplicates (in the case that first name, last name, date-of-birth and street address are not enough to uniquely identify a person.)

Response Codes:

  • 200 - OK. Response payload includes the details requested.

  • 400 - Bad Request. Will respond with a message including details of the request field errors. For example: { "message": "clientProfileId field not supplied." }

  • 401 - Unauthorized. There was an issue with the request. Ensure that all required headers are accurate (X-API-Key, Authorization, Signed-Headers and Host).

  • 5XX - Server Error. Any 5XX error (500, 502, 503, 504) means a Link2Feed error has occurred. Please contact Link2Feed if this persists.

Sample Response:

 

Find a Client by ID (Client Profile ID or Link2Feed ID)

Purpose: This endpoint finds existing clients or fails loudly if it cannot find the client. This is in sharp comparison to the other client-finding endpoints which fail silently and encourage moving down the process of creating a new profile. This endpoint can be used to ensure that a client still exists in the Link2Feed system. This may not always be the case as clients are merged to resolve duplicate profile issues. This endpoint can also be used to convert Client Profile IDs to Link2Feed IDs and back.

HTTP URL: https://{{ HostName }}/api/v1/clients/{{ ID }} where {{ HostName }} is provided by Link2Feed, and varies depending on the environment (Test, Live, Staging, etc) being accessed. {{ ID }} is either the link2feedId or clientProfileId provided by any of the previous calls.

HTTP Method: GET

Request Headers: Authorization, Host, Signed-Headers, X-API-Key

Request Payload: None

Response Format: JSON Object

Response Fields:

  • Sometimes-Present Fields

    • clientProfileId: A globally-unique ID (GUID) representing the client sought for.

    • link2feedId: The client’s unique numerical identifier within the Link2Feed system.

Response Codes:

  • 200 - OK. Response payload includes the details requested.

  • 404 - Not Found. If the ID does not find a unique client, the 404 status will be returned. The payload will include an empty JSON object, with no fields.

  • 401 - Unauthorized. There was an issue with the request. Ensure that all required headers are accurate (X-API-Key, Authorization, Signed-Headers and Host).

  • 5XX - Server Error. Any 5XX error (500, 502, 503, 504) means a Link2Feed error has occurred. Please contact Link2Feed if this persists.

Sample Response for Found Single Client:

 

Find a Client’s Existing Details by ID (Client Profile ID or Link2Feed ID)

Purpose: This endpoint finds existing clients or fails loudly if it cannot find the client. This is in sharp comparison to the other client-finding endpoints which fail silently and encourage moving down the process of creating a new profile. This endpoint also provides a robust set of client personal information, and information for their household.

HTTP URL: https://{{ HostName }}/api/v1/clients/{{ ID }}/details where {{ HostName }} is provided by Link2Feed, and varies depending on the environment (Test, Live, Staging, etc) being accessed. {{ ID }} is either the link2feedId or clientProfileId provided by any of the previous calls.

HTTP Method: GET

Request Headers: Authorization, Host, Signed-Headers, X-API-Key

Request Payload: None

Response Format: JSON Object

Response Fields:

Several of the following fields refer to the data types retrieved from the data types API endpoint.

  • Sometimes-Present Fields

    • clientProfileId: A globally-unique ID (GUID) representing the client sought for.

    • link2feedId: The client’s unique numerical identifier within the Link2Feed system.

    • firstName: The client’s first name.

    • lastName: The client’s last name.

    • dateOfBirth: The client’s date of birth.

    • dobEstimated: A boolean flag for whether or not the above date of birth is an estimate.

    • agencyId: The ID of the client’s preferred agency.

    • noFixedAddress: A flag to check if the client has one of the undisclosed/no-fixed-address/prefer-not-to-answer addresses.

    • addressLine1: The first line of the client’s address.

    • addressLine2: The second line of the client’s address.

    • city: The city of the client’s address.

    • state: The state or province of the client’s address.

    • county: The county of the client’s address.

    • zipCode: The zip or postal code of the client’s address.

    • gender: The client’s gender as recorded in the system.

    • employmentType: The client’s recorded employment type.

    • educationType: The client’s highest received level of education.

    • ethnicity: An array representing the chosen ethnicities for the client.

    • housingType: The type of dwelling for the client.

    • selfIdentificationType: An array representing the chosen self-identifies as options for the client.

    • maritalStatus: The client’s recorded marital status.

    • income: The monthly value of the client’s primary income source.

    • incomeType: The type of income that the client receives as their primary income source.

    • otherIncomes: An array holding names of other income types that the client is receiving beyond their primary income source.

    • email: The client’s e-mail, if it exists. May be false if missing.

    • phoneNumber: The client’s phone number, if it exists. May be false if missing.

    • referredBy: The source of referral which directed the client to register at the food bank.

    • socialProgramTypes: An array holding names of any social programs that the client is eligible for.

    • expenseTypes: An array holding names of any expenses that the client is paying for.

    • dietaryConsiderationTypes: An array holding names of any dietary considerations in the household.

    • languageTypes: An array holding any languages spoken in the household.

    • householdMembers: An array holding client records (ie- all the fields above) for each additional client in the household. Plus the following fields unique to household members:

      • relationship: The relationship between this client, and the primary client being searched for by ID above.

Response Codes:

  • 200 - OK. Response payload includes the client details.

  • 404 - Not Found. If the ID does not find a unique client, the 404 status will be returned. The payload will include an empty JSON object, with no fields.

  • 401 - Unauthorized. There was an issue with the request. Ensure that all required headers are accurate (X-API-Key, Authorization, Signed-Headers and Host).

  • 5XX - Server Error. Any 5XX error (500, 502, 503, 504) means a Link2Feed error has occurred. Please contact Link2Feed if this persists.

Sample Response for Found Single Client:

 

Add or Update Clients In the System

Purpose: This endpoint will allow either adding new clients (POST) or updating existing clients (PATCH). The fields required are listed in the data types API as enabledFields.

HTTP URL: https://{{ HostName }}/api/v1/clients where {{ HostName }} is provided by Link2Feed, and varies depending on the environment (Test, Live, Staging, etc) being accessed.

HTTP Method: POST to add, or PATCH to update

Request Headers: Authorization, Content-Type, Host, Signed-Headers, X-API-Key

Request Payload: JSON Object
This object has a variable number of fields, depending on the setup of the individual environment. The expected fields are listed in the data types API response as enabledFields. In general, a valid response to the Client Details API is also a valid request payload for the add/update API.

  • Request Fields

    • clientProfileId: A globally-unique ID (GUID) representing the client being updated. If this is a POST to create a new client record, this must be retrieved by using the above Find API endpoints first to initiate the client sessions.

    • link2feedId: The client’s unique numerical identifier within the Link2Feed system. This field is ignored, but can be included safely.

    • firstName: The client’s first name.

    • lastName: The client’s last name.

    • dateOfBirth: The client’s date of birth.

    • dobEstimated: A boolean flag for whether or not the above date of birth is an estimate.

    • agencyId: The ID of the client’s preferred agency.

    • noFixedAddress: A flag to check if the client has one of the undisclosed/no-fixed-address/prefer-not-to-answer addresses.

    • addressLine1: The first line of the client’s address.

    • addressLine2: The second line of the client’s address.

    • city: The city of the client’s address.

    • state: The state or province of the client’s address.

    • county: The county of the client’s address.

    • zipCode: The zip or postal code of the client’s address.

    • gender: The client’s gender as recorded in the system.

    • employmentType: The client’s recorded employment type.

    • educationType: The client’s highest received level of education.

    • ethnicity: An array representing the chosen ethnicities for the client.

    • housingType: The type of dwelling for the client.

    • selfIdentificationType: An array representing the chosen self-identifies as options for the client.

    • maritalStatus: The client’s recorded marital status.

    • income: The monthly value of the client’s primary income source.

    • incomeType: The type of income that the client receives as their primary income source.

    • otherIncomes: An array holding names of other income types that the client is receiving beyond their primary income source.

    • email: The client’s e-mail, if it exists. May be false if missing.

    • phoneNumber: The client’s phone number, if it exists. May be false if missing.

    • referredBy: The source of referral which directed the client to register at the food bank.

    • socialProgramTypes: An array holding names of any social programs that the client is eligible for.

    • expenseTypes: An array holding names of any expenses that the client is paying for.

    • dietaryConsiderationTypes: An array holding names of any dietary considerations in the household.

    • languageTypes: An array holding any languages spoken in the household.

    • householdMembers: An array holding client records (ie- all the fields above) for each additional client in the household. Plus the following fields unique to household members:

      • relationship: The relationship between this client, and the primary client being searched for by ID above.

Sample Request Payload

 

Response Format: JSON Object

Response Fields:

Several of the following fields refer to the data types retrieved from the data types API endpoint.

  • Sometimes-Present Fields

    • clientProfileId: A globally-unique ID (GUID) representing the client sought for.

    • link2feedId: The client’s unique numerical identifier within the Link2Feed system.

    • message: The error message, if there is one.

Response Codes:

  • 200 - OK. All the requested data is valid and the request is okay, but it is not yet complete. If this status is reached, it will also include the following request body: { "message": "Client data incomplete." }

  • 201 - Created. All the requested data is valid and the request is both okay and complete. The add or update job has been completed.

  • 400 - Bad Request. This status can be reached if:

    • The incorrect data keys are sent across, or

    • An attempt is made to update a client session that has already timed out or no longer exists, or

    • An attempt is made to send an update without a clientProfileId (client session) at all.

  • 401 - Unauthorized. There was an issue with the request. Ensure that all required headers are accurate (X-API-Key, Authorization, Signed-Headers and Host).

  • 5XX - Server Error. Any 5XX error (500, 502, 503, 504) means a Link2Feed error has occurred. Please contact Link2Feed if this persists.

Sample Response for Job Completed:

Appointments API

Purpose: This collection of endpoints are used to create and update appointments for clients.

Get Appointment Availability for a Specific Agency

Purpose: This endpoint finds available appointment slots at an agency. Note: when setting up an agency to use this system, the agency can only have one appointment program available. If more than one appointment program is available, an error will prevent any availability from showing. This is an intentional design feature to simplify the experience of signing up for services at a location.

HTTP URL: https://{{ HostName }}/api/v1/agencies/{{ Agency ID }}/appointments?startDate={{ YYYY-MM-DD }}&endDate={{ YYYY-MM-DD }}&clientProfileId={{ Client ID }} where {{ HostName }} is provided by Link2Feed, and varies depending on the environment (Test, Live, Staging, etc) being accessed. {{ Agency ID }} is from one of the agencies listed in the Data Types API. The query parameters for startDate and endDate are not required – leaving them out will search for appointments for today and tomorrow. clientProfileId is optional, if included it will provide distances between the agency and the client in the response object.

HTTP Method: GET

Request Headers: Authorization, Host, Signed-Headers, X-API-Key

Request Payload: None

Response Format: JSON Array

Response Fields:

  • Sometimes-Present Fields

    • agencyId: The ID of the agency searched for.

    • agencyName: The name of the agency searched for.

    • distanceKm: The straight-line distance between the Client’s household (if their address is available) and the Agency’s address, in kilometres

    • distanceMi: The straight-line distance between the Client’s household (if their address is available) and the Agency’s address, in miles

    • timeSlots: An array of Time Slot objects each of which has:

      • dateFormat: Provides the standard date format that the system uses.

      • availableDateTime: The start date and time of the appointment, based on the agency’s local timezone.

      • availableDate: Specifically the date part of the time slot.

      • availableTime: Specifically the time part of the time slot.

      • availableRange: Both the start and end date and time of the specific time slot.

      • availabilityCount: The number of spots available at this time slot. Note: in some cases this is null, and in other cases it is zero or negative. These are all valid responses in the context of the system (null means the appointment isn’t time-based, zero means there are no available slots left, and negative means it has been over-booked, which can happen if the appointment caseload is not enforced.)

      • availableTimeslot: Fine-grained details of the date and time for the time slot.

      • locationId: The Link2Feed ID of the agency where the time slot is available.

      • location: The name of the agency where the time slot is available.

      • postcodeEligibility: A true/false response for whether or not this client is eligible, based on a postcode restriction – if this option is not present, there is no postcode restriction to consider for this program.

      • streetAddress: The street address of the location where the time slot is available.

    • provisions: A collection of Provision options that are available with this visit.

Response Codes:

  • 200 - OK. Response payload includes the data types details.

  • 400 - Bad Request. Will respond with a message including details of the request field errors. For example: { "message": "agencyId field not supplied." }

  • 401 - Unauthorized. There was an issue with the request. Ensure that all required headers are accurate (X-API-Key, Authorization, Signed-Headers and Host).

  • 404 - Not Found. There are no available appointments during the time period of the search, for the agency in question.

  • 5XX - Server Error. Any 5XX error (500, 502, 503, 504) means a Link2Feed error has occurred. Please contact Link2Feed if this persists.

Sample Response for Valid Timeslots:

Get Appointment Availability for a Whole Network

Purpose: This endpoint finds available appointment slots at all the agencies in a single network.

HTTP URL: https://{{ HostName }}/api/v1/network/{{ Network ID }}/appointments?startDate={{ YYYY-MM-DD }}&endDate={{ YYYY-MM-DD }}&clientProfileId={{ Client ID }} where {{ HostName }} is provided by Link2Feed, and varies depending on the environment (Test, Live, Staging, etc) being accessed. {{ Network ID }} is the ID of the Network organization in Link2Feed that is being queried. {{ Client ID }} is the Link2Feed ID or Link2Feed ClientProfileId (GUID) of the client interested in services. The query parameters for startDate and endDate are not required – leaving them out will search for appointments for today and tomorrow.

HTTP Method: GET

Request Headers: Authorization, Host, Signed-Headers, X-API-Key

Request Payload: None

Response Format: JSON Array

Response Fields:

  • The response is a single Array of multiple Objects, each with the following fields:

    • dateFormat: Provides the standard date format that the system uses.

    • availableDateTime: The start date and time of the appointment, based on the agency’s local timezone.

    • availableDate: Specifically the date part of the time slot.

    • availableTime: Specifically the time part of the time slot.

    • availableRange: Both the start and end date and time of the specific time slot.

    • availabilityCount: The number of spots available at this time slot. Note: in some cases this is null, and in other cases it is zero or negative. These are all valid responses in the context of the system (null means the appointment isn’t time-based, zero means there are no available slots left, and negative means it has been over-booked, which can happen if the appointment caseload is not enforced.)

    • availableTimeslot: Fine-grained details of the date and time for the time slot.

    • distanceKm: The straight-line distance between the Client’s household (if their address is available) and the Agency’s address, in kilometres

    • distanceMi: The straight-line distance between the Client’s household (if their address is available) and the Agency’s address, in miles

    • locationId: The Link2Feed ID of the agency where the time slot is available.

    • location: The name of the agency where the time slot is available.

    • provisions: A collection of Provision options that are available with this visit.

    • postcodeEligibility: A true/false response for whether or not this client is eligible, based on a postcode restriction – if this option is not present, there is no postcode restriction to consider for this program.

    • programId: The ID of the Program that manages the given appointment time slot.

    • programName: The name of the Program that manages the given appointment time slot.

    • streetAddress: The street address of the location where the time slot is available.

Response Codes:

  • 200 - OK. Response payload includes the data types details.

  • 400 - Bad Request. Will respond with a message including details of the request field errors. For example: { "message": "agencyId field not supplied." }

  • 401 - Unauthorized. There was an issue with the request. Ensure that all required headers are accurate (X-API-Key, Authorization, Signed-Headers and Host).

  • 404 - Not Found. There are no available appointments during the time period of the search, for the agency in question.

  • 5XX - Server Error. Any 5XX error (500, 502, 503, 504) means a Link2Feed error has occurred. Please contact Link2Feed if this persists.

Sample Response for Valid Timeslots:

 

Book an Appointment for a Client

Purpose: This endpoint attempts to book an appointment for a client, at an agency. The agency in question must have an available appointment slot at the given time and date.

HTTP URL: https://{{ HostName }}/api/v1/agencies/{{ Agency ID }}/appointments where {{ HostName }} is provided by Link2Feed, and varies depending on the environment (Test, Live, Staging, etc) being accessed. {{ Agency ID }} is from one of the agencies listed in the Data Types API, and also listed as both agencyId and locationId from the Available Appointments API Endpoint.

HTTP Method: POST

Request Headers: Authorization, Content-Type, Host, Signed-Headers, X-API-Key

Request Payload: JSON Object. The fields of this are all required. Dates and times are based on the agency’s time zone. The date and time fields should match up with a date and time retrieved from the Available Appointments API Endpoint. The clientProfileId field should match up with a client as retrieved from the Client search APIs. programId is only necessary when multiple appointment programs are setup at a single Agency.

Response Format: JSON Object

Response Fields:

  • Sometimes-Present Fields

    • appointmentId: The ID of the appointment that was booked.

Response Codes:

  • 201 - Created. The appointment has been created. Its ID is included with the response.

  • 400 - Bad Request. Will respond with a message including details of the request field errors. For example: { "message": "agencyId field not supplied." }

  • 401 - Unauthorized. There was an issue with the request. Ensure that all required headers are accurate (X-API-Key, Authorization, Signed-Headers and Host).

  • 404 - Not Found. There are no available appointments during the time period, for the agency in question.

  • 5XX - Server Error. Any 5XX error (500, 502, 503, 504) means a Link2Feed error has occurred. Please contact Link2Feed if this persists.

Sample Response for A Successfully Booked Appointment:

 

Update or Cancel an Appointment

Purpose: This endpoint attempts to update or cancel an existing appointment for a client, at an agency.

HTTP URL: https://{{ HostName }}/api/v1/agencies/{{ Agency ID }}/appointments/{{ Appointment ID }} where {{ HostName }} is provided by Link2Feed, and varies depending on the environment (Test, Live, Staging, etc) being accessed. {{ Agency ID }} is from one of the agencies listed in the Data Types API, and also listed as both agencyId and locationId from the Available Appointments API Endpoint. The {{ Appointment ID }} represents an existing appointment.

HTTP Method: POST to update, or DELETE to cancel.

Request Headers: Authorization, Content-Type, Host, Signed-Headers, X-API-Key

Request Payload: JSON Object. For updates, the fields are all required. Dates and times are based on the agency’s time zone. The date and time fields should match up with a date and time retrieved from the Available Appointments API Endpoint. No payload is required for a cancellation.

Response Format: JSON Object. The response will be empty for a deletion.

Response Fields:

  • Sometimes-Present Fields

    • appointmentId: The ID of the appointment that was updated.

Response Codes:

  • 200 - OK. The appointment has been updated or cancelled. If it still exists, its ID is included with the response.

  • 400 - Bad Request. Will respond with a message including details of the request field errors. For example: { "message": "agencyId field not supplied." }

  • 401 - Unauthorized. There was an issue with the request. Ensure that all required headers are accurate (X-API-Key, Authorization, Signed-Headers and Host).

  • 404 - Not Found. There are no available appointments during the time period, for the agency in question.

  • 5XX - Server Error. Any 5XX error (500, 502, 503, 504) means a Link2Feed error has occurred. Please contact Link2Feed if this persists.

Sample Response for A Successfully Updated Appointment:

Mark an Appointment Collected

Purpose: This endpoint attempts to mark an existing appointment as collected for a client, at an agency.

HTTP URL: https://{{ HostName }}/api/v1/agencies/{{ Agency ID }}/appointments/{{ Appointment ID }} where {{ HostName }} is provided by Link2Feed, and varies depending on the environment (Test, Live, Staging, etc) being accessed. {{ Agency ID }} is from one of the agencies listed in the Data Types API, and also listed as both agencyId and locationId from the Available Appointments API Endpoint. The {{ Appointment ID }} represents an existing appointment.

HTTP Method: PATCH.

Request Headers: Authorization, Host, Signed-Headers, X-API-Key

Request Payload: Empty

Response Format: JSON Object. The response will be an empty object for successfully updated appointments.

Response Fields:

  • Sometimes-Present Fields

    • message: An error message, if relevant.

Response Codes:

  • 200 - OK. The appointment has been marked as collected.

  • 400 - Bad Request. Will respond with a message including details of the request field errors. For example: { "message": "agencyId field not supplied." }

  • 401 - Unauthorized. There was an issue with the request. Ensure that all required headers are accurate (X-API-Key, Authorization, Signed-Headers and Host).

  • 404 - Not Found. The appointment could not be found.

  • 5XX - Server Error. Any 5XX error (500, 502, 503, 504) means a Link2Feed error has occurred. Please contact Link2Feed if this persists.

Sample Response for A Successfully Updated Appointment:

 

Retrieve Upcoming Appointments for a Client

Purpose: This endpoint retrieves a list of upcoming appointments for a client.

HTTP URL: https://{{ HostName }}/api/v1/clients/{{ Client ID }}/upcoming-appointments where {{ HostName }} is provided by Link2Feed, and varies depending on the environment (Test, Live, Staging, etc) being accessed. {{ Client ID }} is the numeric Link2Feed ID from any of the client search API endpoints.

HTTP Method: GET

Request Headers: Authorization, Host, Signed-Headers, X-API-Key

Request Payload: None

Response Format: JSON Array. The array will consist of appointment objects, if the client has any upcoming appointments.

Response Fields:

  • Sometimes-Present Fields

    • id: The ID number for the appointment.

    • date: The date of the appointment.

    • time: The time of the appointment, in the agency’s time zone.

    • datetime: Both the date and time of the appointment together, in the agency’s time zone.

    • location: A block of information about where the appointment is taking place including:

      • id: The Agency ID of the location.

      • name: The Name of the location.

      • address: The Address of the location, including:

        • addressLine1: The first line of the location’s address.

        • addressLine2: The second line of the location’s address.

        • city: The city of the location’s address.

        • state: The state of the location’s address.

        • postcode: The zip or postal code of the location’s address.

Response Codes:

  • 200 - OK. The request was valid, and the response body will have all of the upcoming appointments for the client.

  • 400 - Bad Request. Will respond with a message including details of the request field errors. For example: { "message": "agencyId field not supplied." }

  • 401 - Unauthorized. There was an issue with the request. Ensure that all required headers are accurate (X-API-Key, Authorization, Signed-Headers and Host).

  • 404 - Not Found. There are no upcoming appointments for the client.

  • 5XX - Server Error. Any 5XX error (500, 502, 503, 504) means a Link2Feed error has occurred. Please contact Link2Feed if this persists.

Sample Response for A Successfully Updated Appointment:

 

Appendix A: Postman Collection Files

The following files represent the above API endpoints using the Postman API testing and requesting tool (https://www.postman.com/).

To utilize these effectively and easily perform the HMAC signing without having to manually recalculate each request, you will need to setup an environment within Postman that includes at least:

  • API URL as provided by Link2Feed (Variable API_URL)

  • API Key as provided by Link2Feed (Variable API_KEY)

  • API Secret Key as provided by Link2Feed (Variable SECRET)

To learn more about setting environments in Postman see: https://learning.postman.com/docs/sending-requests/managing-environments/