Rapattoni Developer Resources

Rapattoni Magic API

Rapattoni offers an API, for Cloud Magic customers, that supports data access using OAuth2 authentication and OData v4 queries.

Authentication

Magic API access is secured via OAuth2; a transaction with our identity server is required to obtain the necessary bearer token. Currently only the Client Credential grant type is supported.

Authentication URL Example:

  • https://api.rapmagic.com/IDServer/identity/connect/token?type=ams&cust=cust

For Client Credential Grant access, the following parameters must be passed in the Body of a POST transaction:

  • grant_type: Client Credential access will always use the client_credentials grant type.
  • client_id: An id provided by the Association staff.
  • client_secret: A value provided by the Association staff, associated with the client_id.
  • scope: Provided by the Association staff. This must match a scope that the API recognizes and that is approved for usage by your credentials. It is part of what defines what you can access in the API.

Please note, standard web browsers cannot pass all of the criteria; a client program or tool should be used. Example tools for testing are Postman and cURL

The raw Body of the request should look similar to the following example:

  • grant_type=client_credentials&client_id=ClientID&scope=Scope&client_secret=Secret

You will also need to include the header:Content-Type: application/x-www-form-urlencoded and ensure that the values contained in the body of the request are properly URL-encoded.

cURL example:

  • curl -X POST -H "Content-Type:application/x-www-form-urlencoded" -H "Content-Length:content_length_int" -d "Grant_Type=client_credentials&Scope=Magic_API&Client_Id=URLEncoded_ClientID&Client_Secret=URLEncoded_ClientSecret" "https://api.rapmagic.com/IDServer/identity/connect/token?type=ams&cust=demo"

If the transaction is successful, then the response body will be a JSON object containing the access token, the token expiration date, and the token type. The token type will always be “bearer”, and the time till the token expires is set by the association, on a client by client basis, based upon their rules and regulations.


API Transactions

All transactions must include the Authorization header with the value being the client’s current bearer token obtained from the transaction with our identity server.

Here is an example of the how the Authorization header with the bearer token should appear in the HTTP request. Please note that the actual token hash will be substantially longer:

  • Authorization: bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiI

Depending on your setup you may need to preemptively URL encode your query. The following is an example of the URL with an encoded query segment:

  • https://api.rapmagic.com/MagicAPI/cust/odata/Members?%24select=MemberKeyNumeric%2CMemberFirstName%2CMemberLastName%2CMemberNationalAssociationId%2COfficeName

Here is an additional example of a request using cURL where only the spaces require encoding

  • curl -X GET -H "Authorization: bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiI" -G -d "$select=MemberKeyNumeric,MemberFirstName,MemberLastName,MemberNationalAssociationId,OfficeName&$filter=MemberKeyNumeric%20eq%2016400" "https://api.rapmagic.com/MagicAPI/cust/odata/Members"

The Magic API utilizes standard OData URIs and commands (ODatav4).

Responses, unless otherwise specified, will be in the JSON format.

Service and Metadata

The Service Document is available via a get request against the root URL (https://api.rapmagic.com/MagicAPI/cust/odata). This document is a standard OData resource listing all top-level entity sets exposed by the service.( ODatav4 10.1)

Querying this endpoint will return a JSON array of all directly queryable entities. Each object will have the following properties:

  • Name matches the name of the entity in the metadata.
  • Kind is the type of object being described.
  • Url is the end point to use in the URL for access.

    {
         "name": "Members",
         "kind": "EntitySet",
         "url": "Members"
    },
    {
          "name": "MemberAssociation",
           "kind": "EntitySet",
           "url": "MemberAssociation"
    },
            

The Metadata Document is available via a get request against the root URL with “/$metadata” appended (i.e. https://api.rapmagic.com/MagicAPI/cust/odata/$metadata). This resource describes the API’s data model; including data types, relationships between entity sets, and available fields (ODatav4 11.1.2). This resource is only available in the XML format.

Each entity definition will begin with the <EntityType> tag containing the Name of the entity.


    <EntityType Name="Members">
        
The first child element listed under the EntityType tag will be the Key definition, this tag will contain child elements defining the key field(s) for the entity. Keys can be used to target a specific record in an entity.

    <Key>
        <PropertyRef Name="MemberKeyNumeric" />
    </Key>
            
The next elements will describe the properties of the entity, these define the available fields and should include the field’s datatype, maximum character length (if applicable), and an annotation containing a plan text description.

    <Property Name="MemberFirstName" Type="Edm.String">
        <Annotation Term="Magic_API.Models.Data.Description" String="The first name of the Member." />
    </Property>
            
The final elements will be the navigation properties. These define entities that can be expanded to. They contain the Name of the navigation property, the Type of the entity and possible Referential Constraints.

    <NavigationProperty Name="Offices" Type="Magic_API.Models.Data.Offices">
        <ReferentialConstraint Property="OfficeKeyNumeric" ReferencedProperty="OfficeKeyNumeric" />
    </NavigationProperty>
    <NavigationProperty Name="PhoneNumbers" Type="Collection(Magic_API.Models.Data.PhoneMember)" />
             
  • Name is the value used in the $expand clause. So to expand to the Offices entity in this case you would use $expand=Offices
  • Type is full name of the entity targeted by the navigation property. While PhoneNumbers is the name of a navigation property above, it’s actually targeting the entity PhoneMember. This means you would look in the metadata for the Entity Type named PhoneMember for more information regarding the entity that navigation property is targeting. If the Type starts with the word Collection, then the mapping between the entity and the navigation property entity is one-to-many (i.e. one record may map to many records, e.g. one member may map to many phone numbers).
  • ReferentialConstraint references the field(s) being used to link records in the two resources; also known as the Foreign Key. In this case the example entity and Offices have an OfficeKeyNumeric field linking them. Usually this reference only appears if the field is not one of the source entity’s keys.

Query Support

Entity Set Queries: All Entity Set queries use the default OData format; the root URL is appended with “/EntitySet” (i.e. to query the Offices Entity Set: https://api.rapmagic.com/MagicAPI/cust/odata/Offices)
When Querying against Entity Sets, the Magic API Supports most OData 4 query options, functions and operators. The below list are those query options and some of their associated supported functions and operators. Please see the OData 4 specification for further information in regards to these:

  • $expand: allows for the inclusion of entities related to the base entity set queried. The relationships between entity sets can be found in the metadata document. Multiple entities can be included with comma delimiting. If the relationship is further than 1 degree of separation than the full path to the targeted entity must be included. (ODatav4 11.2.4.2)
    Examples:
    • Members?$expand=MemberDesignations: this will return Member records and their related MemberDesignations entries. The Metadata will show Members and MemberDesignations are via MemberKeyNumeric.
    • Members?$expand=MemberDesignations($expand=Designations): this will return Member records, their related MemberDesignations entries and the related information to describe the Designations. The Members set links to MemberDesignations via MemberKeyNumeric and the MemberDesignations set links to Designations on the MemberDesignation key.
  • $select: specify fields to be returned, if not included all fields will be returned. For selecting fields from expanded entity set relationships, the select is included with the expanded item. (ODatav4 11.2.4.2)
    Examples:
    • Members?$select=MemberKeyNumeric,MemberFirstName
    • Members?$expand=MemberDesignations($select=MemberDesignation)&$select=MemberKeyNumeric,MemberFirstName
  • $top: specify the number of entities to return (ODatav4 11.2.5.3)
    • Members?$top=10
  • $skip: skip over the first n entities prior to returning data (ODatav4 11.2.5.4)
    Example:
    • Members?$skip=10
  • $orderby: order the results by a specific field’s value; use asc or desc to specify ascending or descending. To order by multiple criteria use comma delimiting(ODatav4 11.2.5.2)
    Examples:
    • Members?$orderby=MemberFirstName asc
    • Members?$orderby=MemberFirstName asc, OfficeName desc
  • $count: $count=true specifies that the total count of entities matching the request must be returned along with the results (ODatav4 11.2.5.5)
    Example:
    • Members?$count=true
  • $filter: restrict the returned entities to only those matching the filter criteria (ODatav4 11.2.5.1)
    • Operators
      • eq: Equal
      • ne: Not equal
      • gt: Greater than
      • ge: Greater than or equal
      • lt: Less than
      • le: Less than or equal
      • and: Logical and
      • or: Logical or
      • not: Logical negation, used in conjunction with other functions and operators to create a negative comparison.
      • add: add to modify a numeric field and utilize the result for comparisons.
      • sub: subtract to modify a numeric field and utilize the result for comparisons.
      • mul: multiply to modify a numeric field and utilize the result for comparisons.
      • div: divide to modify a numeric field and utilize the result for comparisons.
      • (): Functions and operators can be nested using parentheses for precedence.
    • Functions
      • contains: string contains, syntax is: contains(FieldName,’string’)
      • endswith: string ends with, syntax is: endswith(FieldName,’string’)
      • startswith: string starts with, syntax is: startswith(FieldName,’string’)
      • substring: string contains, syntax is: substring(FieldName,1) eq 'string'
      • tolower: string to lower casing
      • toupper: string to upper casing
      • trim: trim all leading and trailing white spaces from a string
      • concat: append one string value to another
      • day: return the day component from a DateTimeOffset or Date
      • hour: return the hour component from a DateTimeOffset
      • minute: return the minute component from a DateTimeOffset
      • second: return the second component from a DateTimeOffset
      • month: return the month component from a DateTimeOffset or Date
      • year: return the year component from a DateTimeOffset or Date
    • Lambda Operators
      • any: returns true if and only if the expression is true for any member of the collection.
        Example: all Members that have any MemberAssociation records with a MemberAssociationStatus equal to A:
        • Members?$expand=MemberAssociation&$filter=MemberAssociation/any(a:a/MemberAssociationStatus eq 'A')
      • all: returns true if the expression is true for all members of the collection
    • Complex Filter Example:
      • Offices?$filter=(endswith(Office_Name,'Realty') and Street_City eq 'Ventura') or Salespersons add 5 gt 10
  • $apply: $apply triggers data aggrigation behavior, at this time only the groupby extension is supported. (ODatav4 Extension for Data Aggregation Section 3)
    • groupby: groupby takes one or two fields, and returns a distinct list of those fields's values.(ODatav4 Extension for Data Aggregation Section 3.10)
    • Example, the following would return a distinct set of the Event_Type and EventDescriptions for all EventTypes assigned to EventsAndClasses records:
      • EventsAndClasses?$apply=groupby((EventType/Event_Type,EventType/Description))
  • &: Multiple query options can be included at once, each separated by an “&”
    Example:
    • Example: Members?$expand=MemberDesignations($select=Designations)&$top=50&$select=MemberKeyNumeric
  • Paging: Server paging is enabled; the server will limit the number of records that it sends in a single response.
    • @odata.nextLink: If the number of records matching the query parameters is greater than the number of records the server is capable of returning, then the results will include the “@odata.nextLink” JSON object. This object will usually exist at the end of the current result and will contain the exact URL and query parameters needed to obtain the next page of matching records. If this object is not included in the result, then there are no additional pages available.
    • 
      Paging Example
      
      Query:https://api.rapmagic.com/MagicAPI/cust/odata/Members?$select=MemberCity
      
      Result:
      {
      "@odata.context": "https://api.rapmagic.com/MagicAPI/CUST/odata/$metadata#Members(MemberCity)",
      "value": 
          [
                  {
                  "MemberCity": "Somewhere"
                  },
                  {
                  "MemberCity": "Elsewhere"
                  },
                  ...
                  {
                  "MemberCity": "Somewhere"
                  }
          ],
      "@odata.nextLink": "https://api.rapmagic.com/MagicAPI/cust/odata/Members?$select=MemberCity&$skip=500"
      }
                                  

  • Single Entity: To return one specific Entity, the format is EntitySet(key). For example, if pulling back member number 100 from the Members entity set, the root URL would be appended with /Members(100). Some Entity Sets have multiple primary keys, in such cases the request format would be EntitySet(keyfield1=intvalue,keyfield2='charvalue',...). Please refer to the metadata to find the primary key(s) for each Entity Set.
    • Example: https://api.rapmagic.com/MagicAPI/cust/odata/Members(100)
    • Example: https://api.rapmagic.com/MagicAPI/cust/odata/InternetInformation(RecordKey=4,RecordType='MI',Association='ASOC')

Batching

Multiple HTTP GET, POST and/or PATCH transactions may be sent within the body of a single POST request targeting the $batch endpoint.

Required Headers: The following headers MUST be included with their respective values:

  • Authorization:bearer token
  • Content-Type:multipart/mixed;boundary=boundy_value

  • The body of a batch request is made up of a series of individual requests and change sets, each represented as a distinct MIME part (i.e. separated by the boundary defined in the Content-Type header). Each request with in the batch is processesed sequentially and the reponse will be multipart/mixed.

    Each MIME part for the individual requests MUST include the following headers and values:

  • Content-Type:application/http
  • Content-Transfer-Encoding:binary

  • It is prefered that the Absolute URI is used for each individual request.

  • i.e. GET https://qaapi.rapmagic.com/MagicAPI/cust/odata/Members HTTP/1.1

  • If performing POST or PATCH requests, further boundry wrapping must occur for the entirety of the items being changed or created.

    The following is the Body of an example $batch request performing multiple POST transactions

    
         --batch_boundry
         Content-Type: multipart/mixed;boundary=changeset_changes
    
         --changeset_changes
         Content-Type: application/http
         Content-Transfer-Encoding:binary
         Content-ID: 1
    
         POST https://qaapi.rapmagic.com/MagicAPI/cust/odata/EventGuests  HTTP/1.1
         Content-Type: application/json
         Accept: application/json
    
         {"Event_ID":"2016LAY","Registration_ID":"4J5JMC004","Table_Number":0,"Meal_Choice":"V","Last_Name":"Six",
         "First_Name":"Guest","Middle_Initial":"T","Nickname":"","Company_Name":"Test"}
         --changeset_changes
         Content-Type: application/http
         Content-Transfer-Encoding:binary
         Content-ID: 2
    
         POST https://qaapi.rapmagic.com/MagicAPI/cust/odata/EventGuests  HTTP/1.1
         Content-Type: application/json
         Accept: application/json
    
         {"Event_ID":"2016LAY","Registration_ID":"4J5JMC004","Table_Number":0,"Meal_Choice":"V","Last_Name":"Seven",
         "First_Name":"Guest","Middle_Initial":"T","Nickname":"","Company_Name":"Test"}
         --changeset_changes--
         --batch_boundry--
    

    For more detailed information regarding $batch transactions please refer to (ODatav4 Batch Requests Section 11.7)


    Update Transactions

    Records are Updated via an HTTP PATCH request against a Single Entity.The updatable fields are listed in the Updatable API Fields documentation.

    Required Headers: The following headers MUST be included with their respective values:

  • Authorization:bearer token
  • Content-Type:application/json

  • Optional Headers: By Default a successful PATCH request will return a 204 response. If you wish for the record targeted to be returned with a 200 response instead, you may use the following Header:Value :

  • Prefer:return=representation
  • Note that you may include OData query criteria in the URL,such as $select, to narrow the fields shown in the result set when using the optional Prefer header.

    The body of the request must be a JSON object with the following format (quotes included): {"FieldName":"NewValue"}

    Multiple fields may be modified at once with comma delimiting: {"FieldName1":"NewValue1","FieldName2":"NewValue2"}

    Example of a PATCH request to update MemberPassword using cURL:

  • curl -X PATCH "https://api.rapmagic.com/MagicAPI/cust/odata/Members(4567)" -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiI" -H "Content-Type: application/json" -H "Content-Length: 25" -H "Prefer: return=representation" -d "{\"MemberPassword\":\"1234\"}"

  • Insert Transactions

    Records are Inserted via an HTTP POST request. The fields that MUST be included in the object are listed in the Insertable API Records documentation, and will also be included in the error response when submitting a POST request against a valid endpoint without including a body.

    Required Headers: The following headers MUST be included with their respective values:

  • Authorization:bearer token
  • Content-Type:application/json

  • The body of the request must be a JSON object with formatting similar to the following example: {"Event_ID":"EVENTID3","Member_Number":1234,"Table_Number":5,"Meal_Choice":"CH","Num_Tickets":1,"Comment":"Something"}

    A successful POST will return a 201 Created response code and the newly created record.

    Example of a POST request to insert an EventRegistration record using cURL:

  • curl -X PATCH "https://api.rapmagic.com/MagicAPI/cust/odata/EventRegistration" -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiI" -H "Content-Type: application/json" -d "{\"Event_ID\":\"MLTR927A\",\r\n\"Member_Number\":967,\r\n\"Table_Number\":0,\r\n\"Meal_Choice\":\"\",\r\n\"Num_Tickets\":1,\r\n\"Comment\":\"test\"\r\n}"


  • HTTP Response Codes

    Identity Server

    Code Text Description

    200

    OK

    Success

    400

    Bad Request
    “error: unsupported_grant_type”

    The grant type entered during Authentication is not supported.

    400

    Bad Request
    “error: invalid_client”

    The client secret included is invalid.

    415

    Unsupported Media Type

    The Content-Type header includes an unsupported value for this request.

    500

    Internal Server Error

    Likely the cust query string value is incorrect or the client_id is invalid.

    Magic API

    Code Text Description

    200

    OK

    Success

    201

    Created

    The record has been successfully created.

    400

    Bad Request
    “The request is badly formed.”

    Likely the query needs to be URL encoded.

    400

    Bad Request
    “The query parameter 'x' is not supported.”

    The given query parameter is not valid.

    400

    Bad Request
    "Could not find a property named 'x' on type 'entityset'."

    The given property doesn’t exist in the entity set being queried.

    401

    Unauthorized
    “Authorization has been denied for this request.”

    The bearer token passed is expired or invalid.

    403

    Forbidden: Queries against x are rescricted

    You have not been grated access to the targeted endpioint.

    403

    Forbidden: Filter with x is not allowed

    You have not been grated access to search using the given field.

    404

    Not Found

    An invalid resource was targeted

    500

    Internal Server Error

    Most likely occurs due to an issue on the server side.


    Available API Fields