Top 5 API Features to Extend HubSpot Capabilities – Part 4: Custom Cards

Share

Share on facebook
Share on twitter
Share on linkedin

This blog post is part of our 5-part series about HubSpot API Features. In case you missed Part 3, check it out here!

In this fourth installment of our HubSpot API series, we’ll learn how to create a front-end widget for our external data that lives directly on your HubSpot records. In other words, any non-HubSpot sourced data can be pulled in and displayed onto a contact, company, deal, or ticket record without actually living in the HubSpot database (we’ll get into why storing data this way can be particularly useful later). These displays can also be built so that the user can interact with the external data from the HubSpot record itself.

These widget displays, or Custom Cards, are configurable via the API and UI as part of an OAuth’ed HubSpot app. In this article, we’ll walk through how to create and install a card app onto a HubSpot account, from scratch, with both methods. And if you’re not familiar with what these apps are or how they work (or just need a refresher), don’t fret – we’ll review them first before digging into the configuration.

What are Custom Cards?

Cards are external data widgets that live on HubSpot CRM records, which can be viewed by users. When a card app is installed in a HubSpot account, it’s associated with one or more default objects (contacts, companies, deals, and/or tickets). When a user views one of these object records, HubSpot will send an outbound request to an endpoint that you specify. The middleware layer responsible for that endpoint needs to be configured to handle that request and respond with data in a format that HubSpot expects. If successful, the data your middleware responds with will be displayed on an association card on the record:

Demo tickets screenshot

Image sourced from developers.hubspot.com

That’s pretty cool and can be useful in a number of cases, but the real magic lies in the interactableness (it’s a word now! 😉) of the widget. Not only can you view external data, but you can build your app to allow users to interact with the external source right from the card in HubSpot. Common actions include: adding data to items, deleting items, notifying users in the external system of something… really anything that makes sense for your use case can be configured.

Example Use Case for Custom Cards

Before we put fingers to the keyboard, let’s review an example use case that we’ll follow throughout the duration of the tutorial to help contextualize everything.

Let’s say our sales team uses HubSpot to prospect and close service-based deals. Once a deal is won, our project team gets started on fulfilling that service and uses another third-party tool to track the progress of the project. Back in HubSpot, our sales team likes to follow up with these new clients after a certain period of time, to check in on status and try to upsell with additional services.

Let’s assume our sales team wants to see the progress of a project on a given deal within the HubSpot tool (so they don’t have to system-hop or reach out to the project team). This data doesn’t need to live in HubSpot though – that is, the data needs to be viewable but not necessarily exist as record-level data. 

Custom cards can be created to do exactly that – a project’s progress and other useful information can be displayed right on a deal record to provide the sales rep with more insight into the project.

App Infrastructure

Now that we understand why we’re building a card app, let’s take a look at how we’ll be building it. As we mentioned earlier, once a card app is installed on a HubSpot account, whenever a user views a card on a deal record, HubSpot will automatically send an outbound request to our middleware layer. That middleware layer must respond in a specific format that HubSpot can understand and display on the card.

That said, we’ll need to build a piece of middleware that sits between HubSpot and the project management tool backend. We’ll use Python’s Flask framework to handle the requests to and from HubSpot, as it’s lightweight and easy to use, and Ngrok for test connection, but feel free to use whatever toolset you like. Here’s the flow we’ll ultimately need to follow:

User clicks into a Deal record → HubSpot sends request to our Flask endpoint (to be created) → Flask searches our fictional project backend by HubSpot Deal ID and returns its data → HubSpot displays said data on the card

App Authorization

In order to configure custom cards, you’ll need to properly create and authenticate a developer app with your target HubSpot account. HubSpot uses the OAuth 2.0 grant type protocol, a specific authorization flow the app must follow.

This flow first requires the app to launch a browser window to send the user to HubSpot’s OAuth server, where the user approves the request in the browser by selecting the HubSpot portal in which to install the app. The user then receives an authorization code back in the app, which needs to be exchanged for an access token. So, in order, this flow requires 4 steps:

  1. The app opens a browser window to send the user to HubSpot’s OAuth 2.0 server
  2. The user grants permission to the app and selects the HubSpot portal to connect the app to
  3. The user is redirected back to the app with an authorization code in the query string
  4. The app exchanges that authorization code for an access token

Here’s a detailed walkthrough of this process that you can follow to get the app installed.

Once installed, you’re ready to start building!

Create a Card in HubSpot

Now that we’ve covered what a card app is, how it works, and how to install it, we can (finally) start building. We have our app created in our developer account and installed in our HubSpot instance (we recommend starting with a sandbox or test account before installing anything in production), so we’ll now add the Custom Card functionality to the app.

Frontend

The card setup can be done on the frontend by clicking into your App in your Developer Portal and then clicking CRM cards under the Features section. From here, click Create CRM card and name it Projects.

1. Data request

Our card app will be deal-based, so in the Data request tab, we’ll want to click the switch on the Deals Record Type. We’ll also choose hs_object_id as the property HubSpot will send to our Flask middleware – this will send the deal ID as a query parameter to our endpoint.

For the Data fetch URL, we’ll want to drop in the Flask endpoint that will handle the main process logic (more on this in the next section). Ultimately, this app would be deployed through a web service (we like Heroku) but for testing purposes, we’ll use Ngrok, which will provide us with a temporary URL.

You can leave this blank for now – we’ll be spinning up an Ngrok URL and dropping it here a bit later.

2. Properties

Next, navigate to the Card properties tab to create the data points to display on the card. We’ll create three:

project_status, due_date, and project_type with the following field types: status, date, string, respectively. Status fields are essentially picklist fields with predefined color blocks – we’ll give our field three options: in_progress, complete, not_started

3. Custom actions

As we mentioned earlier, we can also configure our app to not only display our external data but be able to interact with our external data as well. While we won’t cover how to do this in this tutorial, it might make sense for this use case to configure the cards to have a button that the sales reps can click on and mark when follow-up for that deal/project was done, which would then display on the card. Take a look at the full HubSpot documentation to learn how to set this up.

Back-end

Alternatively, this setup can be done on the backend, via the API. Check out HubSpot’s documentation for request examples here.

Flask Configuration

Again, our Flask middleware app will need to catch the outbound request that HubSpot sends whenever a user views a card on the UI and then return data to display on the card. We’ll want to create two Python files; one to handle the main routing logic (webhook handling) and another to handle the lookups and returns. Let’s write the latter first so we can call it into the route file. 

For the sake of simplicity, we’re going to represent the project management tool backend as a local SQLite database, called card.db. In the database, we have a simple table called project, which looks like this:

id

objectId

title

project_status

due_date

project_type

1

9682825112

OBO Integration Project

in_progress

2022-12-31

integration

2

9682825112

OBO Consulting Project

complete

2022-07-01

consulting

Make sure that the values in the objectId column are actual deal IDs in your sandbox/test HubSpot instance. 

Next, in a file called projects.py, we’ll write two functions; one for connecting to the SQLite database and another to take in a deal ID, search the table for rows with that deal ID, and return an object that we’ll drop into the response in our to-be-created routing file.

				
					import sqlite3


def connection():
    # connection object
    conn = sqlite3.connect('card.db')
    # set row factory on connection object (returns dict rows)
    conn.row_factory = sqlite3.Row
    # cursor object
    cur = conn.cursor()

    return conn, cur


def return_projects(deal_id):
    conn, cur = connection()
    # find rows in project table by deal_id
    cur.execute("""SELECT * FROM project where objectId = '%s'""" % deal_id)
    rows = cur.fetchall()

    # append dict rows to list
    results = []
    for row in rows:
        results.append({k: row[k] for k in row.keys() if 'id' != k})  # if block excludes table id key/val
    print(results)

    # close the connection
    conn.close()

    return results
				
			

Here’s what that returned object would look like were we to print it:

				
					[{'objectId': '9682825112', 'title': 'OBO Integration Project', 'project_status': 'in_progress', 'due_date': '2022-12-31', 'project_type': 'integration'}, {'objectId': '9682825112', 'title': 'OBO Consulting Project', 'project_status': 'complete', 'due_date': '2022-07-01', 'project_type': 'consulting'}]
				
			

As you’ve probably noticed, we made things simple here by naming the table columns the same as the card fields, which greatly simplifies the return logic. In a true real-world scenario, this will more than likely be a bit more involved. Check the full HubSpot documentation for specifics on how to format the response.  

With that noted, let’s now create a file called app.py to handle the actual routing. Here, we’ll:

  1. Import the Flask package along with our projects.py file
  2. Initialize the Flask instance
  3. Create a route and function to catch the webhook, parse the deal ID from the querystring, and send the deal ID into our return_projects function
  4. Set our port for local testing
				
					from flask import Flask, request
import projects

app = Flask(__name__)


@app.route('/card')
def card():
    deal_id = request.args['associatedObjectId']

    db_results = projects.return_projects(deal_id)
    res = {
        "results": db_results
    }
   
    return res, 200


if __name__ == '__main__':
    app.run(debug=True, port=9999)
				
			

We’re returning the object along with a 200 code if successful.

App Testing

Now that we have our code written, let’s run our app to make sure it’s working properly. In a terminal, navigate to your project directory and make sure Ngrok is installed there. You can enter the following command: ngrok -v to double check (and of course, see the version). 

To deploy an Ngrok instance, enter the command ngrok http 9999 (we chose 9999 as the port number in the app.py file). An http and https URL will spin up and display in the terminal – go ahead and copy the https URL to your clipboard.

Next, head back to your HubSpot app and drop that URL postfixed with /card into the Data fetch URL box in the Data request tab (as we walked thru earlier), and save:

Data fetch URL

Now, run your app.py file. You’ll see something like this printed to the terminal:

				
					 * Serving Flask app app (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://127.0.0.1:9999/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 634-508-112
				
			

This means that the app is up and running and ready to listen for HubSpot webhooks.

Head on over to your HubSpot sandbox or test instance and click into a deal record with an ID found in the SQLite table. If everything was set up correctly, you’ll see a card app with data pertaining to the deal’s project:

OBO custom card

Woohoo! You just created your first card app! Pretty easy right?

Final Thoughts

And with that, we’ve created an automated process to increase the efficiency of the upsell process for sales reps. Project status(es) are clearly displayed on a closed deal’s record, providing the rep with key follow-up information without having to system-hop or manually check in with the project team.

Note that we were able to quickly create and install a card app with minimal code, but keep in mind that our use case was simple in nature and is by no means exhaustive in terms of functionality. We didn’t tutorial the “action hooks” feature, which allows you to create buttons on your card for users to interact with the data and backend, as this is a bit more involved but we implore you to learn more about further customizations through HubSpot’s documentation.

So to recap this tutorial, we:

  1. Created and installed a custom app
  2. Configured the card setting
  3. Built a lightweight Flask middleware layer
  4. Test deployed our app with Ngrok

Now you can take what you’ve learned here and apply it to a full scale application! And as always, feel free to drop us a line if you’re interested in collaborating on an app build or any of our other services.

Interested in joining the obo team?

Related Posts

Get the Latest.

Sign up for monthly blog notifications to learn more about the latest sales and marketing trends.

Ready to drive results?

We want to help your business be what you envision it to be.
Schedule your free consultation here now.

OutboundOps, LLC (dba obo.)

STANDARD TERMS AND CONDITIONS

These Standard Terms and Conditions (the “Terms”) set forth the terms and conditions that govern purchases by any purchaser (the “Client”) of outbound demand generation services and other related services (the “Services”) from OutboundOps, LLC dba obo. Agency (“obo. Agency”). The Terms and any purchase orders, scopes of work and other agreements regarding the Services shall be referred to as the “Agreement.”

1. OFFER FOR SALE.

All agreements between the Client and obo. Agency to purchase the Services shall be governed by the terms and conditions herein. The Client and obo. Agency agree that any modifications, changes, alterations of the terms and conditions herein, with respect to any specific proposal, must be in writing and signed by the Client and obo. Agency. obo. Agency hereby objects to any additional or different terms which may be contained in any of the Client’s purchase orders, acknowledgements or other documents or any communications received from the Client, and the Client and obo. Agency hereby agree that any such attempts shall be null and void and not deemed a part of the terms and conditions hereunder or any resulting order. 

Any offer hereunder shall expire thirty (30) days following its date, unless the Client executes and returns to obo. Agency that proposal for the applicable Services within such thirty (30) day period. No order may be cancelled, modified or altered by the Client, without written consent of obo. Agency, which may be withheld in its sole discretion.

2. FEES AND PAYMENT.

The fees for the Services are set forth in the applicable proposal provided by obo. Agency and otherwise are based on obo. Agency’s current fees, in effect at the time of order, for the Services. The Client acknowledges and agrees that, if it purchases Services with a minimum period for the Services, such amounts shall be due and payable if this Agreement is terminated sooner.

obo. Agency shall provide the Client with invoices, no more frequently than monthly, for the fees due from the Client under the Agreement. All payments for the Services are payable only in United States Dollars. The Client shall make payment for any and all monthly fees on or before the first day of the applicable month for Services. Unless obo. Agency requires payment in advance or upon different terms, for any other services, the Client shall make payment for all fees within thirty (30) days following the date of invoice.

Subject to the limitations above, payments may be made only in cash or by check or wire transfer or by certain credit cards provided that Client provides credit card authorization satisfactory to obo. Agency.

Charges will be assessed on past due accounts as follows: (i) a late charge at a rate equal to the lesser of one and one-half percent (1.5%) per month or the highest rate permitted by applicable law, and (ii) reasonable collection costs and expenses, including attorneys’ fees and court costs.

The Client’s failure to pay in accordance with the provisions of this Section 2 shall entitle obo.

Agency, without prejudice to its rights to damages, to suspend or cancel any outstanding orders or Services or require further assurance of payment from the Client.

3. TERM AND TERMINATION.

The term of this Agreement shall commence on the effective date as set forth in the applicable proposal, and if not specified, on the date that the proposal is signed (the “Effective Date”) and shall continue in effect, until terminated, in accordance with the terms and conditions set forth in this Agreement, until the date that is the time period specified in the applicable proposal following the Effective Date (and if not specified for six (6) months following the Effective Date, and shall automatically renew for additional terms of equal period unless either party provides thirty (30) days’ written notice to the other party at any time and for any reason whatsoever of its intention to terminate the agreement for convenience (the “Term”).

Either party may terminate this Agreement for a material breach of any provision of this Agreement by the other party upon fourteen (14) days’ prior written notice to the other party, such notice to set forth in detail such breach, and the breaching party’s failure to cure such breach. Either party may terminate this Agreement immediately without breach or penalty by written notice to the other party in the event the other party: (i) institutes or has instituted against it proceedings for bankruptcy (which, in the case of proceedings against it, shall remain for ninety (90) days undismissed), (ii) shall consent to the appointment of a receiver for all or substantially all of its property, (iii) shall make a general assignment for the benefit of its creditors, or shall admit in writing its inability to pay its debts as they become due; or (iv) shall be adjudged a bankrupt or insolvent by a court of competent jurisdiction.

At obo. Agency’s sole discretion, the Services may be immediately terminated or suspended if the Client violates any part of this Agreement. Upon termination of obo. Agency’s engagement hereunder, the Client shall pay to obo. Agency the fees payable to obo. Agency for the Services rendered through the date of termination in accordance with Section 2 hereof.

4. WARRANTY.

obo. Agency warrants to the Client that the Services shall meet the requirements of the applicable proposal and industry standards for a period of sixty (60) days from the date of delivery of the Services to the Client. For purposes of clarity, this limited warranty shall not be applicable to: (a) technical and other issues related to the Client’s website, hardware, software or data that are not related to the Services, including without limitation, development, creation and enhancement of the Client’s website, (b) technical and other issues resulting from any third party’s services or involvement regarding the Client’s website or (c) technical or other issues related to Client’s compliance with data security and other privacy laws that are not within the scope of the obo. Agency Services hereunder.

obo. Agency’s sole responsibility shall be, at its option, during the warranty period either: (i) to repair any warranty issues related to the Services or (ii) to refund to the Client the amounts paid during the warranty period, less a reasonable allowance for use, for such Services with warranty issues.

THIS WARRANTY IS THE SOLE AND EXCLUSIVE WARRANTY GIVEN BY OBO. AGENCY WITH RESPECT TO THE SERVICES PROVIDED BY OBO. AGENCY. EXCEPT AS EXPRESSLY SET FORTH HEREIN, TO THE MAXIMUM EXTENT PERMITTED BY LAW, OBO. AGENCY DISCLAIMS ALL WARRANTIES OF ANY KIND, EITHER EXPRESS, IMPLIED, STATUTORY OR COMMON LAW, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND TITLE. SOME JURISDICTIONS DO NOT ALLOW THE WAIVER OR EXCLUSION OF SOME WARRANTIES SO THEY MAY NOT APPLY. IF THIS EXCLUSION IS HELD TO BE UNENFORCEABLE BY A COURT OF COMPETENT JURISDICTION, THEN ALL EXPRESS, IMPLIED AND STATUTORY WARRANTIES SHALL BE LIMITED IN DURATION TO A PERIOD OF SIXTY (60) DAYS FROM THE DATE OF PROVISION OF EACH PORTION OF THE SERVICES, AND NO WARRANTIES SHALL APPLY AFTER THAT PERIOD.

5. LIMITATION OF LIABILITY.
THE CLIENT EXPRESSLY UNDERSTANDS AND AGREES THAT OBO. AGENCYSHALL NOT BE LIABLE TO THE CLIENT OR ANY THIRD PARTY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, PUNITIVE, CONSEQUENTIAL OR EXEMPLARY DAMAGES, EVEN IF OBO. AGENCY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, WHETHER SUCH LIABILITY IS BASED UPON CONTRACT, TORT, NEGLIGENCE OR OTHER LEGAL THEORY. THE CLIENT EXPRESSLY UNDERSTANDS AND AGREES THAT OBO. AGENCY’S CUMULATIVE LIABILITY TO THE CLIENT UNDER THIS AGREEMENT SHALL NOT EXCEED THE AGGREGATE AMOUNT PAID TO OBO. AGENCY UNDER THIS AGREEMENT DURING THE FOUR (4) MONTH PRIOR TO ANY CLAIM.

The Client acknowledges that all delivery dates are approximate. In no event shall obo. Agency be liable for any delays in delivery of the Services.

6. INTELLECTUAL PROPERTY.

obo. Agency agrees that the Client shall own all right, title and interest in and to any pre-existing works of Client, including without limitation, content owned by Client that is provided to obo. Agency (the “Pre-Existing Works”). In the event that any Pre-Existing Works are incorporated into or are used in conjunction with the Services under this Agreement, then during the Term, the Client hereby grants to obo. Agency a fully paid up, non-exclusive, non-transferable, non-sublicensable license to use the Pre-Existing Works solely to provide the Services hereunder.

Upon payment in full for all Services rendered under this Agreement, obo. Agency hereby transfers and assigns to the Client all right, title and interest in and to all work performed in conjunction with the Services, but not including the Licensed IP. For purposes of this Agreement, “Licensed IP” shall mean any and all photographs, artwork and other content and materials that were licensed (not purchased by obo. Agency) for the Services. During the Term, obo. Agency hereby grants to the Client a fully paid up, non-exclusive, non-transferable, non-sublicensable license to use the Licensed IP solely in connection with the Services.

The Client acknowledges that obo. Agency retains all right, title and interest in and to any and all processes, procedures, methods and know-how related to the performance of the Services and any and all related copyrights, trademarks, patents, trade secrets and other intellectual property and proprietary rights. obo. Agency’s name and logo, and all related service names, marks and slogans are the trademarks, service marks or registered trademarks of obo. Agency and may not be used or modified in any manner without the prior written consent of obo. Agency.

7. CONFIDENTIALITY.
At all times during the term of this Agreement and for two (2) years thereafter, the receiving party shall keep confidential and not disclose, directly or indirectly, and shall not use for the benefit of itself of any other third party any Confidential Information of the disclosing party, except that the receiving party may disclose Confidential Information of the disclosing party to its employees and subcontractors to the extent necessary to enable each party to exercise its rights hereunder. “Confidential Information” means any trade secrets or information whether in written, digital, oral or other form which is confidential or proprietary to the disclosing party, including, but not limited to, software, inventions, customer lists, financial information, business methods and processes, and any other materials or information related to any aspect of the business or activities of the disclosing party which are not generally known to others engaged in similar businesses or activities. Notwithstanding the foregoing, Confidential Information does not include information which: (i) was publicly known or generally known within the trade at the time of disclosure; (ii) becomes public knowledge or generally known within the trade without breach of this Agreement by either party or any of its directors, officers or employees; (iii) was information already known by the receiving party at the time of disclosure without a duty of confidentiality, or information independently developed by the receiving party’s personnel who did not have access to the information disclosed by the disclosing party; (iv) is required to be disclosed by law; or (v) is obtained by a party, its officers or employees from third parties who are under no obligation of confidentiality with respect to the information. If the receiving party is required to disclose any Confidential Information by a court order or other specific governmental action, the receiving party may comply with such disclosure requirement, unless the disclosing party, at its own expense, is successful in having the effect of such requirement stayed pending an appeal or further review thereof, or revised, rescinded or otherwise nullified. In all events, the receiving party agrees to notify the disclosing party promptly if at any time a request or demand of any kind is made to the receiving party to disclose any of the disclosing party’s Confidential Information. The disclosing party shall have the right, at its cost, to intervene in any proceeding in which the receiving party is being asked to disclose any of the disclosing party’s Confidential Information.

8. TAXES AND OTHER CHARGES.
The Client shall pay, in addition to the prices as set forth herein, any and all occupation tax, use tax, property tax, sales tax, excise tax, value-added tax, duty, custom, inspection or testing fee, or any other tax, fee or charge of any nature whatsoever, except for taxes on obo. Agency’s income, imposed by any governmental authority on or measured by the transaction between obo. Agency and the Client. The Client shall indemnify, defend and hold harmless obo. Agency against all claims, losses, damages, liabilities, costs and expenses, including reasonable attorneys’ fees, to the extent such claims arise out of any breach of this Section.

9. REPRESENTATIONS.
The Client represents and warrants to obo. Agency that: (i) he is at least 18 years old; (ii) in the event that the Client is an entity, that it has the full right, power and authority to enter into this Agreement; (iii) the performance by the Client of its obligations and duties hereunder, do not and will not violate any agreement to which the Client is a party or by which the Client is otherwise bound; and (iv) the Client’s use of the Services complies in all respects with all applicable laws, statutes, regulations, ordinances and other rules including without limitation, all Federal, state and international laws in connection with data security and privacy of personal data of any identifiable natural person. The Client further represents and warrants that the Client shall ensure that privacy notices posted on Client’s website shall inform users of their rights under all applicable laws.
.
The Client further represents and warrants to obo. Agency that the Client shall not violate, misappropriate or infringe upon any patent, copyright, trademark, trade secret and/or other intellectual property or proprietary rights of any third party.

10. INDEMNIFICATION.
The Client shall indemnify, defend and hold harmless obo.Agency and its directors, officers, employees and agents from and against any and all claims, losses, damages, liabilities, costs and expenses, including reasonable attorneys’ fees, that arise out of, result from or are related to (i) a breach by the Client of any warranty, representation or covenant set forth herein, (ii) the Client’s negligence or willful misconduct, and (iii) violation, misappropriation or infringement upon any patent, copyright, trademark, trade secret and/or other intellectual property or proprietary rights of any third party.

11. GOVERNING LAW.
THE PARTIES AGREE THAT THIS AGREEMENT AND THE RELATIONSHIP BETWEEN THE PARTIES SHALL BE GOVERNED BY AND CONSTRUED IN ACCORDANCE WITH THE LAWS OF THE STATE OF MARYLAND, WITHOUT REGARD TO ITS PRINCIPLES OF CONFLICTS OF LAWS AND WITHOUT REGARD TO THE UNIFORM COMPUTER INFORMATION TRANSACTIONS ACT. THE PARTIES AGREE THAT THE UNITED NATIONS CONVENTION ON CONTRACTS FOR THE INTERNATIONAL SALE OF GOODS SHALL NOT APPLY TO THIS AGREEMENT. THE PARTIES AGREE TO SUBMIT TO THE EXCLUSIVE  JURISDICTION AND VENUE OF THE FEDERAL AND/OR STATE COURTS IN THE STATE OF MARYLAND FOR THE RESOLUTION OF ANY DISPUTES AMONGST THE PARTIES UNDER THIS AGREEMENT.

12. NOTICES.
Any notice provided pursuant to this Agreement shall be in writing and shall be deemed given (i) if by hand delivery, upon receipt thereof; (ii) if mailed, two (2) days after deposit in the U.S. mails, postage prepaid, certified mail return receipt requested, or (iii) if sent via overnight courier, upon receipt.

13. GENERAL INFORMATION.
This Agreement constitutes the entire agreement between the parties with respect to the subject matter herein, superseding any prior agreements between the parties. The Client further acknowledges and agrees that the Client may not assign any part of this Agreement without obo. Agency’s prior written consent, which may be withheld at its sole discretion. This Agreement shall inure to the benefit of each party’s successors and assigns. obo. Agency shall not be deemed to be in breach of the Agreement and thereby liable to the Client or any third party for any delays in the performance of its obligations hereunder caused by fire, explosion, act of God, strikes, war, riot, government regulation, inability to obtain necessary labor, materials or manufacturing facilities or any other act or cause beyond the reasonable control of obo. Agency. The failure of obo. Agency to exercise or enforce any right or provision of this Agreement shall not constitute a waiver of such right or provision. If any provision of this Agreement is found by a court of competent jurisdiction to be invalid, the parties nevertheless agree that the court should endeavor to give effect to the parties’ intentions as reflected in the provision, and the other provisions of this Agreement shall remain in full force and effect.

14. CONTACTING OBO.AGENCY
If the Client has any questions about this Agreement, or any question or problem regarding the Services, the Client can contact obo. Agency by mail at:
obo. Agency
7165 Columbia Gateway Drive, Suite A

Columbia, MD 21046

Or by telephone at (410) 650-5708.

Effective: August 01, 2019.

obo. : Privacy Policy

Purpose

This privacy notice discloses the practices for obo. Agency (OBO) and applies to information collected by this website.

OBO places a high value on your privacy and the expectation that any information collected by OBO remains confidential and is made available only to persons who have a legitimate right to know. OBO recognizes that all employees have an ethical and legal obligation to keep your information confidential and to protect and safeguard this information against unauthorized use. 

Information We Collect

OBO only has access to collect confidential information that you choose to disclose. Confidential information includes, but is not limited to: name, email address, phone number, and address. 

OBO is the sole owner of the information collected and will not sell, trade, or give any confidential information to a third party without express permission. OBO will use gathered information to respond to you regarding the reason you contacted OBO or display/deliver materials, such as emails and content.

Disclosure of Information

An employee may access, discuss, use, and disclose confidential information only for OBO business as it relates to that employee’s specific job functions and/or responsibilities. Only “Minimally Necessary” information may be disclosed within OBO. “Minimally Necessary” means that only the amount of confidential information necessary to accomplish the intended purpose may be disclosed.

Access to Information

Confidential information may only be accessed by employees if related to specific job functions and responsibilities.

If you wish to correct, update, or otherwise modify information provided to OBO, please reach out via email or phone number. You may opt out of future correspondence at any time by contacting OBO via email or phone number.

Security

OBO has security measures in place to protect against the loss, misuse, or alteration of any information under our control, both online and offline.

Change to This Privacy Policy

This website privacy policy is effective as of the date of its posting. OBO may change this privacy policy over time.

How to Contact Us:

If you have any questions regarding this privacy policy, please contact OBO at office@oboagency.com or 410-650-5708 with a detailed description of your inquiry. 

Last Updated October 7th, 2021