def from_api(cls, api, **kwargs):
        if not cls._api_attrs:
            raise NotImplementedError()
        def resolve_attribute_type(attr_type):
            while isinstance(attr_type, list):
                attr_type = attr_type[0]
            if attr_type == 'self':
                attr_type = cls
            if attr_type == 'date':
                attr_type = datetime.datetime.fromtimestamp
            if attr_type is str:
                attr_type = unicode
            if hasattr(attr_type, 'from_api'):
                return lambda **kw: attr_type.from_api(api, **kw)
            return attr_type
        def instantiate_attr(attr_value, attr_type):
            if isinstance(attr_value, dict):
                return attr_type(**attr_value)
            return attr_type(attr_value)
        def instantiate_array(attr_values, attr_type):
            func = instantiate_attr
            if isinstance(attr_values[0], list):
                func = instantiate_array
            return [func(val, attr_type) for val in attr_values]
        def instantiate(attr_value, attr_type):
            if isinstance(attr_value, list):
                return instantiate_array(attr_value, attr_type)
            return instantiate_attr(attr_value, attr_type)
        instance = cls(api)
        for attr_name, attr_type, attr_default in cls._api_attrs:
            attr_value = kwargs.get(attr_name, attr_default)
            if attr_value is TypeError:
                raise TypeError('{} requires argument {}'.format(cls.__name__, attr_name))
            attr_type = resolve_attribute_type(attr_type)
            if attr_value != attr_default:
                attr_value = instantiate(attr_value, attr_type)
            if attr_name == 'from':
                attr_name = 'froom'
            setattr(instance, attr_name, attr_value)
        return instance