.wpb_animate_when_almost_visible { opacity: 1; }
United Way - Party Management - Discover
API TMF 632 Party Management

Table of Contents

This document is a complement to TMF 637 documentation regarding the technical details mandated by the TM Forum applied to our application (https://www.tmforum.org/resources/standard/tmf637-product-inventory-management-api-rest-specification-r19-0-0/)

Authentication prerequisite

Access to this API is secured by the OAuth 2.0 framework with the Client Credentials grant type, which means that you will have to present an OAuth 2.0 access_token whenever you want to request this API.

It's easy to negotiate this access_token: just send a request to the proper token negotiation endpoint, with a Basic Authentication header valued with your own client_id and client_secret.

For this API, the token negotiation endpoint is: https://api.orange.com/oauth/v3/token.

A technical guide is available to learn how to negotiate and manage these access_token.

SDK to manage token lifecycle could help you to implement cache token.

Scopes

Scopes restrict specific request verbs for any resource of this api. You must specify at least one when requesting for an access_token. This is done by adding a scope parameter within the access token request. Scopes are additive and shall be space separated.

As an example:

curl -X POST \
-H "Authorization: Basic NktSSHljksdj7P...Jjndb6UdnlrT2lOaA==" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "Accept: application/json" \
-d "grant_type=client_credentials&scope=owf:united-way:scope1 owf:united-way:scope2" \
https://api.orange.com/oauth/v3/token

Scopes available in this api are explained below.

ScopeDescription
owf:united-way:party:v1:readonlyAllow GET, HEAD http request for any resource of this api
owf:united-way:party:v1:writeAllow POST, PUT, DELETE http request for any resource of this api
  • If your client will only do GET requests, you may request an access_token with '&scope=owf:united-way:party:v1:readonly'.
  • If your client will do GET and POST requests, you must request an access_token with '&scope=owf:united-way:party:v1:readonly owf:united-way:party:v1:write'.

Scopes are not fine-grained permissions. While an access_token can allows your client application to do GET or POST request, the request can be forbidden at the resource level.

We strongly encourage you to register a dedicated client application to subscribe to all United Way apis. You will be able to request an access_token with all scopes required to do a complete scenario over all needed apis.

Important

Please pay particular attention to properly handle authentication error responses in your application. See the section Errors

Base URL

The Base URL is the first part of the full invocation URL, just before the resource paths defined in the API reference.

The Base URL is comprised of the scheme ('https'), the authority (i.e. the Fully Qualified Domain Name) and the API base path.

Whenever you request this API and encounter a 404 NOT FOUND HTTP error response, please check first that the Base URL is correct.

The Base URL for this API is: https://api.orange.com/united-way/discover/party-management/v1

The documentation below assumes that, whenever you make requests on this API, you are prepending the Base URL to the resource paths defined for this API.

Resources

ResourceDescription
OrganizationRetrieve a specific or a collection of organizations.
IndividualManage individuals and their contact information.

Organization

Currently, only read operations are allowed. Organizations are visible from all clients. Organization do not have contactMedium information.

Individual

Individuals of an Organization are transparently isolated from others. Thus, a client application can only see and manage Individuals of the Organization it belongs to.

Creation or modification of Individual must comply with the following rules :

  • familyName and givenName must be set.
  • fullName should be set. It is used to search for individual. You MAY set its value with 'givenName familyName'.
  • at most one contactMedium of the same mediumType and characteristic.contactType can exist.
  • contactMedium must follow this rule matrix:
mediumTypecharacteristic.contactTypemandatory attributes
PHONEFIXED_HOME, FIXED_OFFICE, MOBILE_HOME, MOBILE_OFFICEphoneNumber
PHONEFAXfaxNumber
MAILOTHERemailAddress
ADDRESSSHIPPING_ADDRESS, OTHERfaxNumber

Query resources patterns

Query Resources with attribute selection

In every GET request, you can add a fields parameters to filter the response body with a subset of the attributes.

Example:

GET /individual?fields=fullName,contactMedium.*,contactMedium.characteristic.*
[
    {
        "id": "de76cfa1-9a55-412f-a9ee-61ca2f662a63",
        "fullName": "John Doe",
        "contactMedium": [
            {
                "mediumType": "PHONE",
                "preferred": true,
                "characteristic": {
                    "contactType": "MOBILE_OFFICE",
                    "phoneNumber": "0600000000"
                }
            }
        ],
        "href": "/individual/de76cfa1-9a55-412f-a9ee-61ca2f662a63"
    }
]

For better response time, only request fields you really need. Especially when requesting on the list endpoint.

Note that attributes id and href are always returned, even if fields=none.

Query Resources with attribute filtering

According to TMF630 REST API Design Guidelines, you can filter data by specifying attributes in the querystring. However, not all attributes can be used as a filter criteria. Herein, the exhaustive list of available parameters with the associated allowed operators:

Organization attribute filter

  • name: =, *= with patterns like *foo* (corresponding to a contains pattern)
  • tradingName: =, *= with patterns like foo* (corresponding to a start with pattern) or *foo* (corresponding to a contains pattern)
  • isHeadOffice: =
  • isLegalEntity: =
  • nameType: =
  • organizationType: = and attribute value must be one of COMPANY, DEPARTMENT, UNKNOWN.
  • organizationIdentification: identificationType and identificationId must be present together. identificationType support only = operator and attribute value shall be one of codeArcepRip, rceId, trigramRip, siren. identificationId support = operator. If identificationType is siren, identificationId also support *= with patterns like *123* (corresponding to a contains pattern). See below use cases.

Individual attribute filter

  • fullName: =, *= with patterns like foo* (corresponding to a start with pattern) or *foo* (corresponding to a contains pattern)
  • familyName: =, *= with patterns like foo* (corresponding to a start with pattern) or *foo* (corresponding to a contains pattern)
  • givenName: =, *= with patterns like foo* (corresponding to a start with pattern) or *foo* (corresponding to a contains pattern)
  • legalName: =, *= with patterns like foo* (corresponding to a start with pattern) or *foo* (corresponding to a contains pattern)
  • title: =
  • middleName: =
  • namePrefix: =
  • gender: =
  • partyCharacteristic: =. name and value must be present together and name criteria must be Category. See below use cases.

For detailed information on parameters, check the API reference

Query Resources with iterators

When requesting collections, you should set pagination query parameters.

  • offset: Requested index for start of resources to be provided in response requested by client.
  • limit: Requested number of resources to be provided in response requested by client.

After each request, explore the http headers to retrieve the number of results

  • X-Result-Count: The number of matching resources in the JSON response.
  • X-Total-Count: The total number of matching resources.

If X-Total-Count is bigger than X-Result-Count, you need to request again by incrementing the offset query parameter with the X-Result-Count value. You can limit the number of result per page with limit.

Note that you can't request more result per page than the default value for limit. Be sure to read the header X-Result-Count.

For example, to retrieve only the second element in the list

GET /individual?fields=none&limit=1&offset=1
[
    {
        "id": "de76cfa1-9a55-412f-a9ee-61ca2f662a63",
        "href": "/individual/de76cfa1-9a55-412f-a9ee-61ca2f662a63"
    }
]

Accept-Range is ignored.

Sorting

The query parameter sort is used to sort the resultset in the order specified by the fields listed as value. The default direction is ascending order, use the - modifier to sort in descending order.

Example:

GET /organization?fields=name&offset=0&limit=2&sort=name
HTTP/1.1 200 OK
X-Result-Count: 2
X-Total-Count: 2
[
   {
        "id": "056a5d86-fc14-4361-94d9-014c8d7bc0fe",
        "href": ".../organization/056a5d86-fc14-4361-94d9-014c8d7bc0fe",
        "name": "1.0 ACOLA"
   },
   {
        "id": "14854edb-a763-4963-b8f2-4c29be96b467",
        "href": ".../organization/14854edb-a763-4963-b8f2-4c29be96b467",
        "name": "118000"
   }
]

Resource Individual do not support sorting.

Errors

Failure to code a proper management of the error responses in your application may affect its resilience. Access to the API may be revoked if your application generates too many mishandled errors.

Your application must parse the returned HTTP response to check if an error is returned instead of a 200 OK. Orange APIs use appropriate HTTP status codes to indicate any request processing error, providing detailed information about the underlying fault. This helps you provide better feedback to your users and implement failure recovery mechanisms in your application.

For details on the main error codes, response format, tips and troubleshooting, see our Handling API errors guide

Errors 401

If you get a status code 401 with the error code 42 (such as below), then you have to request a new access token.

HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
  "code": 42,
  "message": "Expired credentials",
  "description": "The requested service needs credentials, and the ones provided
  were out-of-date."
}

Token lifetime

  • Each access_token has a lifetime validity period. This validity period may change overtime to comply with security rules.
  • The token server has a maximum hourly quota per client application to prevent from misuse. Therefore, DON'T request an access_token each time you invoke the service API. DON'T hard-code a validity duration in your application. Instead, your application must parse the returned status code and error code to check if it needs to request a new access token.

For other 401 errors: check that you provide the right Authorization header with the right Bearer

Errors 400

In case of invalid request to the API, you will receive a 400 error code with detailed information in the body message, such as:

HTTP/1.1 400 Bad Request
{
  "code": 25,
  "description": "Missing header",
  "message": "...."
}

Use cases

1. I want to search for my organization entity to place a quote

Other United Way apis require a relatedParty referencing my organization, for eg. placing a quote. Therefore, given a siren, I want to retrieve my organization entity to pass it to other api.

You can lookup for the organization filtering on organizationIdentification.

GET /organization?organizationIdentification.identificationType=siren&organizationIdentification.identificationId=999999&fields=none
HTTP/1.1 200 OK
X-Result-Count: 1
X-Total-Count: 1
[
    {
        "id": "e7dee14c-cd85-495a-9931-ef3c06f2559b",
        "href": ".../organization/e7dee14c-cd85-495a-9931-ef3c06f2559b"
    }
]

2. I want to search for an individual and use it as an interlocutor to place an order

When posting an order, order api require to set a reference to a related party of the 'operatorInterlocutor' category. I want to search for such individuals.

You can lookup for all individual within the Category 'operatorInterlocutor'.

GET /individual?partyCharacteristic.value=operatorInterlocutor&partyCharacteristic.name=Category&fields=fullName
HTTP/1.1 200 OK
X-Result-Count: 1
X-Total-Count: 1
[
    {
        "id": "de76cfa1-9a55-412f-a9ee-61ca2f662a63",
        "fullName": "Jack Dalton",
        "href": "/individual/de76cfa1-9a55-412f-a9ee-61ca2f662a63"
    }
]

If the list is too big, you can refine your search with some more filter.

  • full name contains 'Dal'

    GET /individual?partyCharacteristic.value=operatorInterlocutor&partyCharacteristic.name=Category&fullName*=*Dal*&fields=fullName
    
  • full name equals 'Jack Dalton'

    GET /individual?partyCharacteristic.value=operatorInterlocutor&partyCharacteristic.name=Category&fullName=Jack%20Dalton&fields=fullName
    

Retrieving contactMedium attribute is time consuming, select this field only for small resultset.

3. I want to retrieve the details of an individual or organization

Other apis expose related parties, this api can be used to get the detail of those parties.

For e.g., a fragment of a fictious order could be returned as

{
    "id": "1",
    "productOrderItem": [
        {
            "id": "c307eb1e-429d-4fa1-1338",
            "quantity": 1,
            "action": "add",
            "product": {
                "relatedParty": [
                    {
                        "id": "de76cfa1-9a55-412f-a9ee-61ca2f662a63",
                        "href": "/individuals/de76cfa1-9a55-412f-a9ee-61ca2f662a63",
                        "role": "operatorInterlocutor",
                        "@baseType": "RelatedParty",
                        "@referredType": "Individual",
                        "@type": "RelatedParty"
                    }
                ]
            }
        }
    ],
    "relatedParty": [
        {
            "id": "e7dee14c-cd85-495a-9931-ef3c06f2559b",
            "href": "/organizations/e7dee14c-cd85-495a-9931-ef3c06f2559b",
            "role": "buyer",
            "@baseType": "RelatedParty",
            "@referredType": "Organization",
            "@type": "RelatedParty"
        }
    ],
    "@type": "ProductOrder"
}

Given the id or href, you can retrieve all information with a GET on the resource. If you use the id, the attribute @referredType can be used to discriminate the type of the related party.

For Individual, you can use the /individual/{id} path.

GET /individual/de76cfa1-9a55-412f-a9ee-61ca2f662a63
HTTP/1.1 200 OK
{
    "id": "de76cfa1-9a55-412f-a9ee-61ca2f662a63",
    "familyName": "Dalton",
    "fullName": "Jack Dalton",
    "gender": "MALE",
    "givenName": "Jack",
    "contactMedium": [
        {
            "mediumType": "PHONE",
            "preferred": true,
            "characteristic": {
                "contactType": "MOBILE_OFFICE",
                "phoneNumber": "0600000004"
            }
        },
        {
            "mediumType": "MAIL",
            "preferred": false,
            "characteristic": {
                "contactType": "OTHER",
                "emailAddress": "jack.dalton@foo.com"
            }
        },
        {
            "mediumType": "ADDRESS",
            "preferred": false,
            "characteristic": {
                "city": "Somewhere",
                "contactType": "OTHER",
                "postCode": "9999",
                "street1": "21 jump street"
            }
        }
    ],
    "partyCharacteristic": [
        {
            "name": "Category",
            "valueType": "STRING",
            "value": "operatorInterlocutor"
        }
    ],
    "@type": "Individual",
    "href": "/individual/de76cfa1-9a55-412f-a9ee-61ca2f662a63"
}

The same applies to Organization with path /organization/{id}.

4. I want to create an individual

When the individual does not exist yet, I want to create a new individual.

You can do a POST. Don't forget to use an access_token with owf:united-way:party:v1:write scope.

POST /individual
Content-Type: application/json
{
    "familyName": "Dalton",
    "fullName": "Jack Dalton",
    "gender": "MALE",
    "givenName": "Jack",
    "contactMedium": [
        {
            "mediumType": "PHONE",
            "preferred": true,
            "characteristic": {
                "contactType": "MOBILE_OFFICE",
                "phoneNumber": "0600000004"
            }
        },
        {
            "mediumType": "MAIL",
            "preferred": false,
            "characteristic": {
                "contactType": "OTHER",
                "emailAddress": "jack.dalton@foo.com"
            }
        },
        {
            "mediumType": "ADDRESS",
            "preferred": false,
            "characteristic": {
                "city": "Somewhere",
                "contactType": "OTHER",
                "postCode": "9999",
                "street1": "21 jump street"
            }
        }
    ],
    "partyCharacteristic": [
        {
            "name": "Category",
            "valueType": "STRING",
            "value": "operatorInterlocutor"
        }
    ],
    "@type": "Individual"
}
HTTP/1.1 201 Created
Location: /individual/de76cfa1-9a55-412f-a9ee-61ca2f662a63
Content-Type: application/json
{
    "id": "de76cfa1-9a55-412f-a9ee-61ca2f662a63",
    "familyName": "Dalton",
    "fullName": "Jack Dalton",
    "gender": "MALE",
    "givenName": "Jack",
    "contactMedium": [
        {
            "mediumType": "PHONE",
            "preferred": true,
            "characteristic": {
                "contactType": "MOBILE_OFFICE",
                "phoneNumber": "0600000004"
            }
        },
        {
            "mediumType": "MAIL",
            "preferred": false,
            "characteristic": {
                "contactType": "OTHER",
                "emailAddress": "jack.dalton@foo.com"
            }
        },
        {
            "mediumType": "ADDRESS",
            "preferred": false,
            "characteristic": {
                "city": "Somewhere",
                "contactType": "OTHER",
                "postCode": "9999",
                "street1": "21 jump street"
            }
        }
    ],
    "partyCharacteristic": [
        {
            "name": "Category",
            "valueType": "STRING",
            "value": "operatorInterlocutor"
        }
    ],
    "@type": "Individual",
    "href": "/individual/de76cfa1-9a55-412f-a9ee-61ca2f662a63"
}

If the payload is not valid, the server will return a 400.

HTTP/1.1 400 Bad Request
{
  "code": "23",
  "message": "The field familyName is required",
  "reason": "Missing body field",
  "@type": "Error"
}

5. I want to update an individual

You can do a PATCH. Don't forget to use an access_token with owf:united-way:party:v1:write scope.

PATCH /individual/de76cfa1-9a55-412f-a9ee-61ca2f662a63
Content-Type: application/json
{
    "fullName": "Joe Dalton",
    "givenName": "Joe",
    "contactMedium": [
        {
            "mediumType": "ADDRESS",
            "preferred": true,
            "characteristic": {
                "city": "Paris",
                "contactType": "OTHER",
                "postCode": "75002",
                "street1": "1 rue de la paix"
            }
        }
    ],
    "partyCharacteristic": [
        {
            "name": "Category",
            "valueType": "STRING",
            "value": "operatorInterlocutor"
        }
    ]
}
HTTP/1.1 200 OK
Content-Type: application/json
{
    "id": "de76cfa1-9a55-412f-a9ee-61ca2f662a63",
    "familyName": "Dalton",
    "fullName": "Joe Dalton",
    "gender": "MALE",
    "givenName": "Joe",
    "contactMedium": [
        {
            "mediumType": "ADDRESS",
            "preferred": true,
            "characteristic": {
                "city": "Paris",
                "contactType": "OTHER",
                "postCode": "75002",
                "street1": "1 rue de la paix"
            }
        }
    ],
    "partyCharacteristic": [
        {
            "name": "Category",
            "valueType": "STRING",
            "value": "operatorInterlocutor"
        }
    ],
    "@type": "Individual",
    "href": "/individual/de76cfa1-9a55-412f-a9ee-61ca2f662a63"
}

Note that patching arrays like partyCharacteristic or contactMedium is a replace all operation.